doubianxian6557 2017-09-21 02:48
浏览 203
已采纳

Google Drive API v3创建和上传文件

I have a python script that creates a Google Drive file via API and uploads it. I am trying to rewrite the script in Go but the API documentation does not provide a Go quickstart. Here is the python script:

#!/bin/python
from __future__ import print_function
import httplib2
import os

from apiclient import discovery
from oauth2client import client
from oauth2client import tools
from oauth2client.file import Storage
from apiclient.http import MediaFileUpload

try:
 import argparse
 parser = argparse.ArgumentParser(description='Ebay Google Drive Uploader')
 parser.add_argument('-r', metavar="rack",
  help="-r <rack>")
except ImportError:
 parser = None

try:
 args = parser.parse_args()
except:
 print (parser.error)
#print ("parser = ", parser)

if not args.r:
 print ("Please specify rack (-r rack)")
 exit
else:
 #print ("Processing ", args.r)
 sheet_name = args.r + ".csv"
 sheet_filename = '/tmp/' + args.r + '.csv'

# If modifying these scopes, delete your previously saved credentials
# at ~/.credentials/drive-python-quickstart.json
SCOPES = 'https://www.googleapis.com/auth/drive'
CLIENT_SECRET_FILE = 'client_secret.json'
APPLICATION_NAME = 'Ebay Google Drive Uploader - albraden@ebay.com'


def get_credentials():
 """Gets valid user credentials from storage.
 Returns:
  Credentials, the obtained credential.
 """
 home_dir = os.path.expanduser('~')
 credential_dir = os.path.join(home_dir, '.credentials')
 if not os.path.exists(credential_dir):
  os.makedirs(credential_dir)
 credential_path = os.path.join(credential_dir,
  'drive-python-quickstart.json')

 store = Storage(credential_path)
 credentials = store.get()
 if not credentials or credentials.invalid:
  print ("before flow
")
  flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
  print ("flow = ", flow)
  flow.user_agent = APPLICATION_NAME
  if parser:
   credentials = tools.run_flow(flow, store, parser)
  else: # Needed only for compatibility with Python 2.6
   credentials = tools.run(flow, store)
  print('Storing credentials to ' + credential_path)
 return credentials

def main():
 """Creates a spreadsheet using the Google Drive API
 """
 credentials = get_credentials()
 http = credentials.authorize(httplib2.Http())
 service = discovery.build('drive', 'v3', http=http)

 file_metadata = {
  'name' : sheet_name,
  'mimeType' : 'application/vnd.google-apps.spreadsheet'
 }
 media = MediaFileUpload(sheet_filename,
  mimetype='text/csv')
 results  = service.files().create(body=file_metadata,
                                   media_body=media,
                                   fields='id').execute()

 sheet_id = results["id"]
 print (sheet_id)
 #sheet_url = results["webViewLink"]
 #print ('sheet_url = ', sheet_url)
 def callback(request_id, response, exception):
  if exception:
   # Handle error
   print (exception)
  #else:
   #print ("Permission Id: %s" % response.get('id'))

 batch = service.new_batch_http_request(callback=callback)
 domain_permission = {
  'type': 'domain',
  'role': 'writer',
  'domain': 'ebay.com',
  'allowFileDiscovery': True
 }
 batch.add(service.permissions().create(
  fileId=sheet_id,
  body=domain_permission,
  fields='id',
 ))
 batch.execute()

if __name__ == '__main__':
    main()

The problem is that I can't figure out how to specify the media type. In Python I used MediaFileUpload but it looks like Golang requires a different method. Here's what I have in Go:

package main

import (
 "encoding/json"
 "fmt"
 "io/ioutil"
 "log"
 "net/http"
 "net/url"
 "os"
 "os/user"
 "path/filepath"

 "golang.org/x/net/context"
 "golang.org/x/oauth2"
 "golang.org/x/oauth2/google"
 "google.golang.org/api/drive/v3"
)

// getClient uses a Context and Config to retrieve a Token
// then generate a Client. It returns the generated Client.
func getClient(ctx context.Context, config *oauth2.Config) *http.Client {
 cacheFile, err := tokenCacheFile()
 if err != nil {
  log.Fatalf("Unable to get path to cached credential file. %v", err)
 }
 tok, err := tokenFromFile(cacheFile)
 if err != nil {
  tok = getTokenFromWeb(config)
  saveToken(cacheFile, tok)
 }
 return config.Client(ctx, tok)
}

// getTokenFromWeb uses Config to request a Token.
// It returns the retrieved Token.
func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
 authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
 fmt.Printf("Go to the following link in your browser then type the "+
  "authorization code: 
%v
", authURL)

 var code string
 if _, err := fmt.Scan(&code); err != nil {
  log.Fatalf("Unable to read authorization code %v", err)
 }

 tok, err := config.Exchange(oauth2.NoContext, code)
 if err != nil {
  log.Fatalf("Unable to retrieve token from web %v", err)
 }
 return tok
}

// tokenCacheFile generates credential file path/filename.
// It returns the generated credential path/filename.
func tokenCacheFile() (string, error) {
 usr, err := user.Current()
 if err != nil {
  return "", err
 }
 tokenCacheDir := filepath.Join(usr.HomeDir, ".credentials")
 os.MkdirAll(tokenCacheDir, 0700)
 return filepath.Join(tokenCacheDir,
  url.QueryEscape("drive-go-quickstart.json")), err
}

// tokenFromFile retrieves a Token from a given file path.
// It returns the retrieved Token and any read error encountered.
func tokenFromFile(file string) (*oauth2.Token, error) {
 f, err := os.Open(file)
 if err != nil {
  return nil, err
 }
 t := &oauth2.Token{}
 err = json.NewDecoder(f).Decode(t)
 defer f.Close()
 return t, err
}

// saveToken uses a file path to create a file and store the
// token in it.
func saveToken(file string, token *oauth2.Token) {
 fmt.Printf("Saving credential file to: %s
", file)
 f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
 if err != nil {
  log.Fatalf("Unable to cache oauth token: %v", err)
 }
 defer f.Close()
 json.NewEncoder(f).Encode(token)
}

func main() {
 ctx := context.Background()
 b, err := ioutil.ReadFile("/usr/local/lib/client_secret.json")
 if err != nil {
  log.Fatalf("Unable to read client secret file: %v", err)
 }

 // If modifying these scopes, delete your previously saved credentials
 // at ~/.credentials/drive-go-quickstart.json
 config, err := google.ConfigFromJSON(b, drive.DriveFileScope)
 if err != nil {
  log.Fatalf("Unable to parse client secret file to config: %v", err)
 }
 client := getClient(ctx, config)

 srv, err := drive.New(client)
 if err != nil {
  log.Fatalf("Unable to retrieve drive Client %v", err)
 }

 file_metadata := make(map[string]string)
 sheet_name := "SLC:SLC02:02-314:06:04.csv"
 sheet_filename := "/tmp/SLC:SLC02:02-314:06:04.csv"
 file_metadata["name"] = sheet_name
 file_metadata["mimeType"] = "application/vnd.google-apps.spreadsheet"
 media = MediaFileUpload(sheet_filename, mimetype="text/csv")


 r, err := srv.Files.Create(body=file_metadata,
                            media_body=media,
                            fields='id')
 if err != nil {
  log.Fatalf("Unable to create file: %v", err)
 }
}

Can someone provide a working example that creates and uploads a document to Google Drive?

Reference links are here: https://paste.fedoraproject.org/paste/JmElgduugSKLVSAYm1htGw

  • 写回答

1条回答 默认 最新

  • dpgua04022 2017-09-21 06:41
    关注

    How about this sample script? This sample was modified main() of your script. When you use this sample, please replace your main() to mine. In your Python script, it converts from CSV to Spreadsheet and modify the permissions. So also it gave the same flow to this sample.

    Important points :

    1. Give mimeType of file that it wants to upload to options of Media(r io.Reader, options ...googleapi.MediaOption).
    2. In order to give options, use googleapi.ContentType().
    3. Give mimeType of file that it wants to convert, when it uploads it to Google Drive, to file of Create(file *File).
    4. In order to give file, use &drive.File{}.
    5. For installing permissions, use &drive.Permission{}. Each parameter is the same to them for Python.

    Sample script :

    func main1() {
        ctx := context.Background()
        b, err := ioutil.ReadFile("/usr/local/lib/client_secret.json")
        if err != nil {
            log.Fatalf("Unable to read client secret file: %v", err)
        }
    
        // If modifying these scopes, delete your previously saved credentials
        // at ~/.credentials/drive-go-quickstart.json
        config, err := google.ConfigFromJSON(b, drive.DriveFileScope)
        if err != nil {
            log.Fatalf("Unable to parse client secret file to config: %v", err)
        }
        client := getClient(ctx, config)
    
        srv, err := drive.New(client)
        if err != nil {
            log.Fatalf("Unable to retrieve drive Client %v", err)
        }
    
        //  I modified below.
        sheet_name := "SLC:SLC02:02-314:06:04.csv"                     // File you want to upload on Google Drive
        sheet_filename := "/tmp/SLC:SLC02:02-314:06:04.csv"            // File you want to upload on your PC
        baseMimeType := "text/csv"                                     // mimeType of file you want to upload
        convertedMimeType := "application/vnd.google-apps.spreadsheet" // mimeType of file you want to convert on Google Drive
    
        file, err := os.Open(sheet_filename)
        if err != nil {
            log.Fatalf("Error: %v", err)
        }
        defer file.Close()
        f := &drive.File{
            Name:     sheet_name,
            MimeType: convertedMimeType,
        }
        res, err := srv.Files.Create(f).Media(file, googleapi.ContentType(baseMimeType)).Do()
        if err != nil {
            log.Fatalf("Error: %v", err)
        }
        fmt.Printf("%s, %s, %s
    ", res.Name, res.Id, res.MimeType)
    
        permissiondata := &drive.Permission{
            Type:               "domain",
            Role:               "writer",
            Domain:             "ebay.com",
            AllowFileDiscovery: true,
        }
        pres, err := srv.Permissions.Create(res.Id, permissiondata).Do()
        if err != nil {
            log.Fatalf("Error: %v", err)
        }
        fmt.Printf("%s, %s
    ", pres.Type, pres.Role)
    }
    

    Result :

    SLC:SLC02:02-314:06:04.csv, ### file ID on Google Drive ###, application/vnd.google-apps.spreadsheet
    domain, writer
    

    References :

    Also I got the infomation for this sample from godoc and GitHub of google-api-go-client.

    Edit :

    This uses Quickstart. In order to use this sample script, please do the Step 1 and Step 2.

    Or your library may be required to update.

    At this sample script, it works file using google-api-go-client/drive/v3/ of Sep 13, 2017.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示