Skip to content

Instantly share code, notes, and snippets.

@oshiro-kazuma
Created January 27, 2020 01:18
Show Gist options
  • Save oshiro-kazuma/a1878a0655318fdd40055a616552a969 to your computer and use it in GitHub Desktop.
Save oshiro-kazuma/a1878a0655318fdd40055a616552a969 to your computer and use it in GitHub Desktop.
Google Drive APIのサンプルコード
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"golang.org/x/net/context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/drive/v3"
)
// NOTE: https://developers.google.com/drive/api/v3/quickstart/go を参考に作成
// google drive apiのアクセスに使用するhttp.Clientを生成
// Retrieve a token, saves the token, then returns the generated client.
func getClient(config *oauth2.Config) *http.Client {
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
tokFile := "token.json"
tok, err := tokenFromFile(tokFile)
if err != nil {
tok = getTokenFromWeb(config)
saveToken(tokFile, tok)
}
return config.Client(context.Background(), tok)
}
// NOTE: https://developers.google.com/drive/api/v3/quickstart/go を参考に作成
// 認証コードを標準入力で受付て認証する
// Request a token from the web, then 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 authCode string
if _, err := fmt.Scan(&authCode); err != nil {
log.Fatalf("Unable to read authorization code %v", err)
}
tok, err := config.Exchange(context.TODO(), authCode)
if err != nil {
log.Fatalf("Unable to retrieve token from web %v", err)
}
return tok
}
// NOTE: https://developers.google.com/drive/api/v3/quickstart/go を参考に作成
// 認証して作成したtoken.jsonファイルを取得する
// Retrieves a token from a local file.
func tokenFromFile(file string) (*oauth2.Token, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
tok := &oauth2.Token{}
err = json.NewDecoder(f).Decode(tok)
return tok, err
}
// NOTE: https://developers.google.com/drive/api/v3/quickstart/go を参考に作成
// token.jsonを保存する
// Saves a token to a file path.
func saveToken(path string, token *oauth2.Token) {
fmt.Printf("Saving credential file to: %s\n", path)
f, err := os.OpenFile(path, 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 provideGoogleDriveService() *drive.Service {
// credentials.jsonの取得
b, err := ioutil.ReadFile("credentials.json")
if err != nil {
log.Fatalf("Unable to read client secret file: %v", err)
}
// If modifying these scopes, delete your previously saved token.json.
config, err := google.ConfigFromJSON(b, drive.DriveReadonlyScope)
if err != nil {
log.Fatalf("Unable to parse client secret file to config: %v", err)
}
client := getClient(config)
// google drive serviceの取得
service, err := drive.New(client)
if err != nil {
log.Fatalf("Unable to retrieve Drive client: %v", err)
}
return service
}
package main
import (
"fmt"
"io/ioutil"
"log"
"google.golang.org/api/drive/v3"
)
// id=XXX の部分をサンプルコードでは予め定義しています
var (
folderID = "1cIYwjCvZfgzXVO_vkBo0GoJsh7bFi11f" // https://drive.google.com/open?id=1_H4SnrG8cuuGBldIFAkn5veLnRCEEbe3
textFileID = "1_H4SnrG8cuuGBldIFAkn5veLnRCEEbe3" // https://drive.google.com/open?id=1ewvYv12D_ojdXufzTO2kF3um_vAS_N9k
excelFileID = "1ewvYv12D_ojdXufzTO2kF3um_vAS_N9k" // https://drive.google.com/open?id=1cIYwjCvZfgzXVO_vkBo0GoJsh7bFi11f
)
// 実行結果
//
// $ go run main.go client.go
// [2020-01-27T00:08:50.181Z] text.txt
// [2020-01-27T00:08:28.698Z] test.xlsx
// テキストの内容 : xxx yyy
// ファイルのサイズ: 8702
//
// KintoneにGoogle Driveを添付する方法がわからず、ひとまずURLが共有されるという前提でサンプルコードを実装しました。
// URLからfileIDを取得して、それをもとに情報を取得しています。
//
// https://gyazo.com/fb80e1c082e1b727416206e9c17ed1b5
//
// 事前準備
// 下記URLの「Enable the Drive API」ボタンをクリックして credentials.json を取得する必要があります。
// https://developers.google.com/drive/api/v3/quickstart/go
func main() {
// google drive serviceを取得
service := provideGoogleDriveService()
// フォルダ内のファイル一覧を表示(更新日と名前)
// fileIDから、対象がフォルダなのかファイルなのかを識別する方法がわからなかったので、
// 予め指定されたfileIDがフォルダであることをわかる前提で実装しています。
files, err := ls(service, folderID)
if err != nil {
log.Fatalf("Unable to retrieve folder: %v", err)
}
for _, f := range files {
println(f)
}
// テキストファイルを取得して表示する
textFileBinary, err := download(service, textFileID)
if err != nil {
log.Fatalf("Unable to retrieve folder: %v", err)
}
print("テキストの内容 : ")
print(string(textFileBinary))
// Excelファイルを取得し、サイズを表示する
excelFileBinary, err := download(service, excelFileID)
if err != nil {
log.Fatalf("Unable to retrieve folder: %v", err)
}
print("ファイルのサイズ: ")
println(len(excelFileBinary))
}
// フォルダ内のファイル一覧を取得
func ls(service *drive.Service, folderID string) ([]string, error) {
f, err := service.Files.
List().
Q(fmt.Sprintf(`"%s" in parents and trashed = false`, folderID)). // ゴミ箱に入れたファイルは除外、in parents であるフォルダの中を指定
Spaces("drive").
Fields("files(id, name, modifiedTime, createdTime)").
Do()
if err != nil {
return nil, err
}
var files []string
for _, i := range f.Files {
files = append(files, fmt.Sprintf("[%s] %s", i.ModifiedTime, i.Name))
}
return files, nil
}
// ファイルをダウンロード
func download(service *drive.Service, fileID string) ([]byte, error) {
resp, err := service.Files.Get(fileID).Download()
if err != nil {
panic(err)
}
defer resp.Body.Close()
return ioutil.ReadAll(resp.Body)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment