【Java】Google Drive APIでGoogle Driveに接続する方法

Agenda
更新日時

 

最近Google Drive APIを利用する機会があり、API利用までの手順がやや面倒でしたので、備忘録を兼ねてご紹介したいと思います。

プログラムのサンプルはJavaですが、基本はGoogleから提供されているサンプルがベースになります。

API利用までの事前準備は他の言語においても共通になりますので、他の言語を利用の方はGoogleで公開されているサンプルソースをもとにプログラム部分だけ差し替えて読んで頂ければ幸いです。

 


JavaでGoogle Driveへ接続するための事前準備


まずはGoogle Console画面でOAuth認証とGoogle Drive APIの利用登録が必要になります。

【Google Console】

https://console.developers.google.com/

Google APIs

 

「プロジェクトを作成」リンクからプロジェクトを作成します。

Google APIs New Project

 

プロジェクトを作成した後は、「認証情報を作成」からOAuthクライアントIDの作成を行います。

Google APIs Auth Top

 

OAuthクライアントIDを作成する前に同意画面の作成を行います。

Google APIs OAuth Client ID

 

同意画面の設定画面はGSuiteユーザの場合は内部を選択可能ですが、一般的なユーザの場合は外部のみ選択可能です。

OAuth Confirm View

 

同意画面の設定を行います。ひとまずアプリケーション名の設定のみ行います。

OAuth Config

 

同意画面の設定後は先ほどの「認証情報を作成」からOAuthアカウントの作成を行います。アプリケーションの種類は「その他」を選択します。

OAuth Client ID Create

 

OAuthクライアントを作成すると認証情報の一覧に作成したクライアントIDが表示されます。

Created OAuth Client ID

 

作成したクライアントIDをクリックすると詳細画面が表示されるので、詳細画面からJSONファイル(credentials.json)をダウンロードします。

OAuth Detail View

 

これでOAuth認証を利用する準備はできました。

続いて、Google Drive APIの利用を有効にします。「ライブラリ」からAPIライブラリ画面を開きます。

API Library Top

 

Google Drive APIを選択して有効にします。

Google Drive API

以上でJavaからAPIを利用するための準備ができました。

 


JavaでGoogle Driveへ接続する


Google Driveへ接続するにはGoogleから提供されているAPIクライアントを利用します。

サンプルは以下Webページで公開されています。

https://developers.google.com/drive/api/v3/quickstart/java

 

開発用ツールとしてeclipseなどをインストールし、Googleのサンプルと同じくGradleプロジェクトとして作成します。

build.gradleファイルは以下のように設定します。

apply plugin: 'java'
apply plugin: 'application'

mainClassName = 'Quickstart'
sourceCompatibility = 1.8
targetCompatibility = 1.8
version = '1.0'

repositories {
    mavenCentral()
}

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'
}

APIクライアントのバージョンは1.23.0を利用します。

最新版を利用した場合、Driveへ接続する際にエラーとなって接続できませんでした。日々バージョンも上がっておりますので、もしかしたら解消している可能性もありますが、1.23.0は問題なく接続できることを確認済みのため、ひとまずご紹介するバージョンでは1.23.0でご紹介します。

先ほど事前準備でダウンロードしたcredentials.jsonをGradleプロジェクトのsrc/main/resourcesの直下に配置します。

以下、Googleのサンプルを参考にGoogle Drive上にfilesフォルダを作成し、ユーザのホームディレクトリに予め用意したtest.pdfファイルをアップロードし、アップロードしたtest.pdfファイルをダウンロードするサンプルになります。

 

package Quickstart;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.http.FileContent;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;


public class Quickstart {

    private static final String APPLICATION_NAME = "Drive API Java Sample";
    private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".credentials/drive-java-quickstart");
    private static FileDataStoreFactory DATA_STORE_FACTORY;
    private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
    private static HttpTransport HTTP_TRANSPORT;
    private static final List<String> SCOPES = Arrays.asList(DriveScopes.DRIVE);

    static {
        try {
            HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
            DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
        } catch (Throwable t) {
            t.printStackTrace();
            System.exit(1);
        }
    }

    public static Credential authorize() throws IOException {
        InputStream is = Quickstart.class.getResourceAsStream("/credentials.json");
        GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(is));

        GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
                .setDataStoreFactory(DATA_STORE_FACTORY)
                .setAccessType("offline")
                .build();
        Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");

        return credential;
    }

    public static Drive connectDrive() throws IOException {
        Credential credential = authorize();
        return new Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
                .setApplicationName(APPLICATION_NAME)
                .build();
    }

    public static String createFolder(Drive service, String folderName) throws IOException {
        File fileMetadata = new File();
        fileMetadata.setName(folderName);
        fileMetadata.setMimeType("application/vnd.google-apps.folder");

        File file = service.files().create(fileMetadata)
                .setFields("id, name, webContentLink, webViewLink")
                .execute();

        return file.getId();
    }

    public static Map<String,String> upload(Drive service, String folderId, String filePath, String fileName, String mimeType) {
        Map<String,String> ret = null;

        try {
            File fileMetadata = new File();
            fileMetadata.setName(fileName);
            if (Objects.nonNull(folderId)) {
                fileMetadata.setParents(Collections.singletonList(folderId));
            }

            java.io.File localFilePath = new java.io.File(filePath);
            FileContent mediaContent = new FileContent(mimeType, localFilePath);

            File file = service.files().create(fileMetadata, mediaContent)
                    .setFields("id, name, webContentLink, webViewLink")
                    .execute();

            ret = new HashMap<String,String>();
            ret.put("id",file.getId());
            ret.put("name",file.getName());
            ret.put("webContentLink",file.getWebContentLink());
            ret.put("webViewLink",file.getWebViewLink());

        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

        return ret;
    }

    public static void download(Drive service, String fileId, String folderPath, String fileName) {
        java.io.File localFolderPath = new java.io.File(folderPath);
        if (!localFolderPath.exists()) {
            localFolderPath.mkdirs();
        }
        String filePath = "";
        if (Objects.equals(folderPath.substring(folderPath.length()-1),"/")) {
            filePath = folderPath + fileName;
        } else {
            filePath = folderPath + "/" + fileName;
        }
        java.io.File localFilePath = new java.io.File(filePath);
        try(OutputStream os = new FileOutputStream(localFilePath)) {

            service.files().get(fileId).executeMediaAndDownloadTo(os);
            os.flush();

        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    public static void main(String[] args) throws IOException {
        Drive service = connectDrive();
        // create folder
        String folderId = createFolder(service, "files");
        // upload file
        Map<String, String> map = upload(service, folderId, System.getProperty("user.home") + "/test.pdf", "test_googledrive.pdf", "application/pdf");
        // download file
        download(service, map.get("id"), System.getProperty("user.home") + "/", "test_download.pdf");
    }

}

上記プログラムをGUI環境で実行します。eclipseで実行する場合は以下のようにプロジェクトを右クリックしてRun AsメニューからJava Applicationで実行することができます。(選択肢が表示されますので、Quickstartを選択します。)

java run

 

実行するとブラウザが起動して、ログイン画面が表示されます。

Google Login

 

権限付与の確認画面が表示されますので、権限付与を許可します。

Authority Dialog

 

選択内容の確認画面が表示されますので、許可ボタンをクリックします。

Access Confirm

 

ログイン後、StoredCredentialファイルがホームディレクトリの.credentials/drive-java-quickstartの直下に生成されます。

StoredCredential

 

次回以降のアクセスはcredentials.jsonファイルとStoredCredentialファイルがあれば認証可能になり、ブラウザが起動したり、ログインを求められることは無くなります。ただし、権限変更を行う場合や認証情報(クライアントシークレット)を変更する場合は再度credentials.jsonファイルの取得とStoredCredentialファイルを取得する必要があります。

そのため、Google Drive APIを利用したシステムを作成する場合は、StoredCredentialファイル取得用に上記のようなサンプルプログラムを別プロジェクトのアプリケーションで用意しておくと良いと思います。

 

 


まとめ


JavaでGoogle Drive APIを利用するためには以下の手順が必要です。

(1) Google Console画面でプロジェクトを作成する。

(2) OAuth認証の同意画面を設定する。

(3) OAuth認証クライアントを作成する。

(4) OAuth認証クライアントからクライアントシークレット情報が記述されたJSONファイルをダウンロードする。

(5) Google APIライブラリからGoogle Drive APIの利用を有効にする。

(6) Googleが提供するサンプルソースをもとに初回認証を行い、トークンID、リフレシュトークンIDなどが記述されたStoredCredentialファイルを取得する。

以上です。

関連記事
カテゴリ

コメントを追加

この質問はあなたが人間の訪問者であるかどうかをテストし、自動化されたスパム送信を防ぐためのものです。