Google Drive API v3创建并上传文件

时间:2017-09-21 02:48:18

标签: go google-drive-api

我有一个python脚本,可以通过API创建Google云端硬盘文件并上传。我试图在Go中重写脚本,但API文档没有提供Go快速入门。这是python脚本:

#!/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\n")
  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()

问题在于我无法弄清楚如何指定媒体类型。在Python中我使用了MediaFileUpload,但看起来Golang需要一个不同的方法。这就是我在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: \n%v\n", 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\n", 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)
 }
}

有人可以提供一个创建文档并将文档上传到Google云端硬盘的工作示例吗?

参考链接位于:https://paste.fedoraproject.org/paste/JmElgduugSKLVSAYm1htGw

1 个答案:

答案 0 :(得分:3)

这个示例脚本怎么样?此示例已修改为您脚本的main()。使用此示例时,请将main()替换为我的。{1}}。在Python脚本中,它将从CSV转换为电子表格并修改权限。所以它也为这个样本提供了相同的流程。

要点:

  1. 将要上传的mimeType文件提供给options的{​​{1}}。
  2. 要提供Media(r io.Reader, options ...googleapi.MediaOption),请使用options
  3. 将上传到Google云端硬盘时要转换的mimeType文件转换为googleapi.ContentType()的{​​{1}}。
  4. 要提供file,请使用Create(file *File)
  5. 要安装权限,请使用file。 Python的每个参数都与它们相同。
  6. 示例脚本:

    &drive.File{}

    结果:

    &drive.Permission{}

    参考文献:

    此外,我从google-api-go-client的godoc和GitHub获得了此样本的信息。

    编辑:

    这使用Quickstart。要使用此示例脚本,请执行步骤1和步骤2.

    或者您的图书馆可能需要更新。

    在此示例脚本中,它使用2017年9月13日的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\n", 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\n", pres.Type, pres.Role) } 工作文件。