Google Drive REST API

以前 Python で Google Drive にファイルアップロード という記事を書いたがそれの Kotlin (Java) 版である。 Java に関しては Google API Client が用意されているのでそれを導入して指定の手順を踏めば良い。 書くコードは多めなのだが手順としては分かりやすかった。

公式サイトの Quick Start を辿ればファイル一覧取得までは出来るのだが、ここでは「指定のディレクトリにファイルアップロード」までを書くものとする。

公式の Quick Start を Kotlin で書く

まず Google API Developer Console で対象プロジェクトに対し Google Drive API が有効になっていることを確認する。 有効になっていれば「API とサービス -> 認証情報」から「OAuth 2.0 クライアント ID」の認証情報を作成する (既にあればそれを使用する)。 作成したらそれを押下すると「クライアント ID」と「クライアントシークレット」が表示され、画面上部に「JSON をダウンロード」というメニューが表示されるのでそれを押下しダウンロードする。 ファイル名を crient_secret.json とリネームし Java (Gradle) プロジェクトの /src/main/resources 上に配置する。

build.gradle には公式の通り以下を追加する:

dependencies {
    compile 'com.google.api-client:google-api-client:1.23.0'
    compile 'com.google.oauth-client:google-oauth-client-jetty:1.23.0'
    compile 'com.google.apis:google-api-services-drive:v3-rev110-1.23.0'
}

公式の Quick Start 相当のコードは以下となる。 ファイル一覧を取るだけでもコード量は少し長いが、そのまま書けば動いた:

...(略)...
typealias DriveFile = com.google.api.services.drive.model.File  // java.io.File と被るので別名をつける

fun index() {
    val transport = GoogleNetHttpTransport.newTrustedTransport()
    val jsonFactory = JacksonFactory.getDefaultInstance()
    val input = javaClass.getResourceAsStream("/client_secret.json")  // クラスパス上ルートディレクトリにあるものとする
    val clientSecrets = GoogleClientSecrets.load(JacksonFactory.getDefaultInstance(), InputStreamReader(input))
    val scopes = Collections.singletonList(DriveScopes.DRIVE)  // Quick Start と異なり書き込み権限を与えておく
    val flow = GoogleAuthorizationCodeFlow.Builder(transport, jsonFactory, clientSecrets, scopes)
            .setDataStoreFactory(FileDataStoreFactory(File("credentials")))  // 認証情報を格納するディレクトリ
            .setAccessType("offline")
            .build()
    val credentials = AuthorizationCodeInstalledApp(flow, LocalServerReceiver()).authorize("user")
    val service = Drive.Builder(transport, jsonFactory, credentials)
            .setApplicationName("アプリ名")
            .build()
    val files = service.files().list()
            .setPageSize(10)
            .setFields("nextPageToken, files(id, name)")
            .execute()
            .files
    println("files: ${files.map { it.name }}")  // ファイル名の一覧が表示される
}

Collections.singletonList(DriveScopes.DRIVE) の箇所が公式 Quick Start では Collections.singletonList(DriveScopes.DRIVE_METADATA_READONLY) になっているが、これだと読み込みだけの限られた処理しかできない (ファイルを書き込もうとすると例外がスローされる)。 後の手順でファイルアップロードを行うために全権限を付与している。

java.io.File を使わなければならないのに Google Drive API の方のファイルオブジェクトが同名の com.google.api.services.drive.model.File になっているのが少し不便に感じるのでここでは typealias で別名をつけておくとコードがスッキリする。

尚、初回実行時に認証が入るのだが、コンソールに Please open the following address in your browser: (URL) といった出力がされるのでそのリンクを踏んで認証を完了させる。 この認証情報は setDataStoreFactory() で指定したディレクトリに入るので、また認証を行いたい場合はこの中のファイルを削除すればもう一度行うことができる。

指定ディレクトリにファイルアップロード

上記コードからの続きで以下を書く:

    val file = DriveFile()
    file.name = "hogefuga"  // ファイル名
    file.parents = arrayListOf("1b5-2LHlr1j0t6dRIsODNlMRXVJ5TGvos")  // 親ディレクトリ ID
    val content = FileContent("text/plain", File("C:\\Users\\hoge\\fuga.txt"))
    service.files().create(file, content).execute()  // execute() を忘れると実行されないので注意

指定ディレクトリの ID は Web 上の Google Drive にアクセスし対象ディレクトリに移動すると URL に表示されるのでそれを使用すれば良い。