タケユー・ウェブ日報

Ruby on Rails や Flutter といったWeb・モバイルアプリ技術を武器にお客様のビジネス立ち上げを支援する、タケユー・ウェブ株式会社の技術ブログです。

Google API Client for Ruby でGoogleDriveにアップロード

S3などのオブジェクトストレージと比べて面倒

  • フォルダを作る必要がある
  • 同名のフォルダを複数作成できてしまう
gem 'google-api-client'
require 'googleauth'
require 'google/apis/drive_v3'

FOLDER_ID = "xxxxxxxxxxxxxxxxxxxxxx" # https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxxxxx
UPLOAD_FILE_PATH = "/path/to/file.txt"

service_account_key_json = File.read("path/to/service-account.key.json")
drive_folder_id = FOLDER_ID

authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: StringIO.new(service_account_key_json),
  scope: 'https://www.googleapis.com/auth/drive'
)
authorizer.fetch_access_token!

drive = Google::Apis::DriveV3::DriveService.new
drive.authorization = authorizer

drive.create_file(
  {
    name: "file.txt",
    parents: [drive_folder_id],
    modifiedTime: File::Stat.new(UPLOAD_FILE_PATH).mtime
  },
  upload_source: UPLOAD_FILE_PATH 
)

任意のフォルダを作成してアップロード

ちゃんとやるなら排他制御なども考える必要がありそうです。

require 'googleauth'
require 'google/apis/drive_v3'

FOLDER_ID = "xxxxxxxxxxxxxxxxxxxxxx" # https://drive.google.com/drive/folders/xxxxxxxxxxxxxxxxxxxxxx
UPLOAD_FILE_PATH = "/path/to/file.txt"

service_account_key_json = File.read("path/to/service-account.key.json")
drive_folder_id = FOLDER_ID

authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: StringIO.new(service_account_key_json),
  scope: 'https://www.googleapis.com/auth/drive'
)
authorizer.fetch_access_token!

drive = Google::Apis::DriveV3::DriveService.new
drive.authorization = authorizer

# 必要なフォルダがある確認してなければ作成する
folders = "path/to/folder".split("/")
upload_folder_id = folders.each_with_object([drive_folder_id]) { |folder_name, folder_ids|
  folder = drive.list_files(
    q: "mimeType='application/vnd.google-apps.folder' and '#{folder_ids.last}' in parents and name = '#{folder_name}'",
    page_size: 1
  ).files.first
  if folder
    # noop
  else
    folder = drive.create_file({
      name: folder_name,
      mime_type: 'application/vnd.google-apps.folder',
      parents: [folder_ids.last],
    }, fields: 'id')
  end
  folder_ids.push(folder.id)
}.last

drive.create_file(
  {
    name: "file.txt",
    parents: [upload_folder_id],
    modifiedTime: File::Stat.new(UPLOAD_FILE_PATH).mtime
  },
  upload_source: UPLOAD_FILE_PATH 
)