golangでサービスアカウント認証の下、google driveの共有ドライブへファイルをアップロードする

The first post
golang
Author

Masaya Kameyama

Published

July 4, 2021

google drive apiを使ってファイルをアップロードする方法は公式の解説ではgolangのドキュメントが貧弱だ. golangからサービスアカウントで認証し, 共有ドライブ(shared drive)へファイルのアップロードを行おうとするとGoogle APIs Client Library for Goを解読する必要がある. quickstartではOAuth 2.0認証を使ってマイドライブ(mydrive)のファイル一覧を表示するサンプルがある. 少し検索するとOAuth 2.0認証やサービスアカウントでマイドライブへファイルをアップロードする方法が見つかるが, 共有ドライブへのアップロード方法は見つけることができなかったのでその方法を紹介する.

準備

  1. shared driveにdirectoryを作成する(driveIdはhttps://drive.google.com/drive/folders/XXX のXXX部分)
  2. サービスアカウントを発行しcredential.jsonを保存する
  3. google driveの画面 > メンバーを管理 でサービスアカウントを追加し投稿者権限を付与する

サンプルコード

以下のコードはsample.txtをshared driveへアップロードする. driveIdを上の説明を参考に書き換えた後sample.txt, credential.jsonを同じディレクトリに置いて実行する. shared driveへファイルをアップロードするにはSupportsAllDrives(true)とする必要があり, ここに辿り着くまでに時間がかかり面倒だった.

Code
package main

import (

    "encoding/json"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "google.golang.org/api/drive/v3"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "golang.org/x/oauth2/jwt"
)

// ServiceAccount : Use Service account
func ServiceAccount(credentialFile string) *http.Client {
    b, err := ioutil.ReadFile(credentialFile)
    if err != nil {
        log.Fatal(err)
    }
    var c = struct {
        Email      string `json:"client_email"`
        PrivateKey string `json:"private_key"`
    }{}
    json.Unmarshal(b, &c)
    config := &jwt.Config{
        Email:      c.Email,
        PrivateKey: []byte(c.PrivateKey),
        Scopes: []string{
            drive.DriveScope,
        },
        TokenURL: google.JWTTokenURL,
    }
    client := config.Client(oauth2.NoContext)
    return client
}


func main() {


    filePath := "sample.txt"     // file path 
    driveId := "XXX"
    
    //use survice account
    client := ServiceAccount("credential.json") // Please set the json file of Service account.
    
    srv, err := drive.New(client)
    if err != nil {
        log.Fatalf("Unable to retrieve drive Client %v", err)
    }

    uploadFile, err := os.Open(filePath)
    if err != nil {
        log.Fatalf("Cannot find such file %v", err)
    }

    folderIdList := [] string{driveId}
    f := &drive.File{Name: filePath, Parents: folderIdList}

    _, err = srv.Files.Create(f).SupportsAllDrives(true).Media(uploadFile).Do()
    if err != nil {
        log.Fatalf("Upload Failed %v", err)
    }

}
Back to top