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 在若依框架下实现人脸识别
  • ¥15 网络科学导论,网络控制
  • ¥100 安卓tv程序连接SQLSERVER2008问题
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同