Google Drive API で Google ドライブへアクセス
こんにちは、サポート部のまさよしです。
早いもので Google API シリーズも今回で第 5 弾となります。今まで紹介したシリーズについては以下にリンクを貼りましたので、ご興味ある方は是非あわせてご一読ください!
- Google Sheets API を使ってスプレッドシートを操作
- PowerBuilder から Google Spread Sheet に接続してみよう
- Gmail API を使ってメールを操作(前編)
- Gmail API を使ってメールを操作(前編)
そして今回は、PowerBuilder から Google ドライブへのアクセスについてご紹介します。
事前準備
まずは Google API シリーズのお作法として、Google ドライブへのアクセスについても Google Cloud Platform 上で Google Drive API の有効化や認証情報の設定が事前に必要です。基本的には Google Sheets API や Gmail API の利用と同様ですが、Google API シリーズを初めて読まれる人もいるかと思いますので、手順を説明します。なお、詳細な設定方法については Web 上で『Google Drive API』を検索すると有益な情報が拾えますので、環境によって適宜設定してください。
今回も検証目的なので Google Cloud Platform の無料トライアルを利用していますが、Google Cloud Platform の設定で Google API シリーズで変わる部分は 5 と 6 となります。
- Google Cloud Platform にログイン後、プロジェクトを作成して Google Drive API を有効にします
- ナビゲーション メニューから「IAM と管理」-「リソースの管理」をクリック
- リソースの管理画面で「プロジェクトを作成」をクリック
- 新しいプロジェクト画面でプロジェクト名を入力し [作成] ボタンをクリック
- 作成したプロジェクトがドロップダウンで選択されているのを確認後、ナビゲーション メニューから「API とサービス」-「ライブラリ」をクリック
- API ライブラリ画面で表示されている Google Workspace カテゴリから Google Drive API を選択
- Google Drive API 画面の[有効にする] ボタンをクリック
- 有効にした Google Drive API の認証情報を設定します
- ナビゲーション メニューから「API とサービス」-「認証情報」をクリック
- 認証情報画面で「認証情報を作成」をクリック後、「OAuth クライアント ID」をクリック
- OAuth クライアント ID の作成画面でアプリケーションの種類の選択や OAuth クライアントの名前を入力後、[作成] ボタンをクリック
作成が無事終わるとクライアント ID とクライアント シークレットが表示されます。クライアント ID とクライアント シークレットは PowerBuilder 内の処理で使用するので、忘れないようテキストで保存 or メモしておいてください。仮に忘れてしまった場合、認証情報画面の OAuth 2.0 クライアント ID リストから OAuth クライアントの名前をクリックすれば再表示できますので、ご安心を!
Google Cloud Platform 側の設定はこれにて完了です。
Authorization Code の生成と Access Token の取得
次に PowerBuilder アプリケーションを作成します。
Google Drive API を利用するにあたり、承認済みのリクエストとして Access Token をあわせて送信する必要があります。Access Token は、まず Google にログインして Authorization Code を生成後、Authorization Code とクライアント ID、クライアント シークレットを送信することで取得できます。
今回も Authorization Code 生成用に ShellExecuteW 関数を使用します。ShellExecuteW 関数の引数で指定した URL をデフォルトブラウザーで起動させますので、Global External Functions に関数の宣言を記述します。
※ PowerBuilder 2019 R3 の「新しい WebBrowser コントロール」を組み込めばこの部分は改善ができるかもしれませんので、次回の記事ではそちらも記載予定です。
Global External Functions
FUNCTION Long ShellExecute ( Uint ihwnd, String lpszOp, String lpszFile, String lpszParams, String lpszDir, Int wShowCmd ) LIBRARY "Shell32.dll" ALIAS FOR "ShellExecuteW"
ブラウザーは、ウィンドウ上に用意したボタンクリック時に立ち上げるようにします。サンプルスクリプトは、以下の記述となります。
[Authorization Code 生成] ボタン Clicked イベント
// 変数宣言 String ls_id String ls_redirect String ls_scope String ls_url String ls_null // Null セット SetNull( ls_null ) // クライアント ID と Redirect URI、Scope を設定 ls_id = "生成されたクライアント ID" ls_redirect = "urn:ietf:wg:oauth:2.0:oob" ls_scope = "https://www.googleapis.com/auth/drive.readonly" // 認証リクエスト用 URL 作成 ls_url = "https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=" + ls_id + "&redirect_uri=" + ls_redirect + "&scope=" + ls_scope // URL を引数としてブラウザーをオープン ShellExecute( 0, "open", ls_url, ls_null, ls_null, 0 ) // 終了 Return
変数 ls_id は OAuth クライアント ID の設定時に生成されたクライアント ID を設定します(忘れた場合は Google Cloud Platform の認証情報画面に GO!)。また変数 ls_redirect は urn:ietf:wg:oauth:2.0:oob を指定していますが、この値は Google の承認サーバーが承認コードをブラウザーのタイトル バーに返すようです。
そして大事な Scope です。今回はフォルダーやファイルの一覧を取得するため、ファイル(フォルダー)読み取り専用の drive.readonly を変数 ls_scope で指定しています。間違ったリクエストを送信してファイルの書き込みや削除、ファイルのアップロード / ダウンロード、ゴミ箱への移動などしたくないですからね。なお、Google Drive API の Scope に関しては Google Drive for Developers > Drive API (V3) のリファレンスを確認してください。
生成した Authorization Code は Access Token 取得時にリクエストパラメーターとして送信するので、インスタンス変数などで保持しておいてください。今回のアプリケーションではシングルラインエディットで明示的に保持しておきます。
次に生成した Authorization Code から Access Token を取得する処理を記述します。各処理(Authorization Code 生成や Access Token 取得、Google ドライブアクセス)を単純化させたいため、取得した Access Token の保持先としてインスタンス変数を用意しておきます。
Instance Variables
String is_access_token
以下は OAuthClient オブジェクトを使用して Access Token を取得するサンプルスクリプトになります。Access Token 取得には先ほど生成した Authorization Code とクライアント ID、クライアント シークレットをリクエストパラメーターとして送信します。
[Access Token 取得] ボタン Clicked イベント
// 変数宣言 Integer li_rtn String ls_id String ls_secret String ls_redirect String ls_scope String ls_authorization OAuthClient loa_client TokenRequest ltr_request TokenResponse ltr_response // Access Token 初期化 is_access_token = "" // パラメーター設定 ls_id = "生成されたクライアント ID" ls_secret = "生成されたクライアント シークレット" ls_redirect = "urn:ietf:wg:oauth:2.0:oob" ls_scope = "https://www.googleapis.com/auth/drive.readonly" // シングルラインエディットから Authorization Code 取得 ls_authorization = sle_1.Text IF IsNull( ls_authorization ) OR Trim( ls_authorization ) = "" THEN Return END IF // OAuthClient 作成 loa_client = CREATE OAuthClient // Authorization Code から Access Token を取得する ltr_request.Tokenlocation = "https://accounts.google.com/o/oauth2/token" ltr_request.Method = "POST" ltr_request.Granttype = "authorization_code" ltr_request.Clientid = ls_id ltr_request.Clientsecret = ls_secret // パラメーターを追加 ltr_request.ClearParams() ltr_request.AppendParam( "grant_type", "authorization_code" ) ltr_request.AppendParam( "client_id", ls_id ) ltr_request.AppendParam( "client_secret", ls_secret ) ltr_request.AppendParam( "scope", ls_scope ) ltr_request.AppendParam( "code", ls_authorization ) ltr_request.AppendParam( "redirect_uri", ls_redirect ) // Content-Type ヘッダーを設定 ltr_request.ClearHeaders() ltr_request.SetHeader( "Content-type", "application/x-www-form-urlencoded" ) // トークン情報取得をリクエスト li_rtn = loa_Client.AccessToken( ltr_request, ltr_response ) // 破棄 DESTROY loa_client IF li_rtn = 1 AND ltr_response.GetStatusCode() = 200 THEN // Access Token 取得 is_access_token = ltr_response.GetAccessToken() // メッセージ MessageBox( "確認", "Access Token を取得しました" ) ELSE MessageBox( "エラー", "Access Token の取得に失敗しました", StopSign! ) END IF // 終了 Return
Access Token を取得するために AccessToken 関数を使用してリクエストを送信します。なお、AccessToken 関数を呼び出す前に TokenRequest オブジェクトに認証サーバー URL やプロセスの種類、HTTP メソッドなどを設定する必要がありますのでお忘れなく!
ここまでは今まで紹介した Google API シリーズの処理とほぼ変わりないので「過去の記事を流用して手抜きしてるんじゃない!?」と誤解されてしまうかもしれませんが、もう一歩踏み込んで考えてください。別の見方をすると、ここまでの処理を共通化すれば、仮に新規であろうと既存であろうとそのモジュールを組み込むことで、Google Drive API や Google Sheets API、Google Drive API 機能の早期実現化に繋がらないでしょうか?繋がりますよね?(すみません。半分自己正当化してますw)
PowerBuilder から Google ドライブへアクセス
最後は PowerBuilder から Google ドライブへアクセスする処理を記述しますが、今回はシンプルにマイドライブにある「無題のフォルダー」に保存されているファイル(フォルダー)の一覧を取得してみましょう。「無題のフォルダー」の構成は以下のとおりです。
Google ドライブのファイル(フォルダー)の一覧を取得するには https://www.googleapis.com/drive/v3/files/ に GET リクエストを送信します。結果として kind(リソースの種類) や id(ファイル / フォルダーのID)、name(ファイル / フォルダーの名前)、mimeType(MIME タイプ)といった情報が JSON 形式のデータで返ってきます。
また、ファイル / フォルダーの絞り込み(名前や ID、MIME タイプ [フォルダー / ファイル指定]、更新日付、書き込み権限など)を行うには、URL にクエリパラメーター(q)で指定します。例えば、今回対象の「無題のフォルダー」を指定する場合、’ID’ in parents といったクエリをパラメーターとして付与します。なお、ID はブラウザー上でフォルダーを選択した際に表示される URL の folders/ 以下となります。クエリパラメーターの詳細は Google Drive for Developers リファレンス – Search for files and folders でご確認ください。
加えて、その他の絞り込みとしてゴミ箱にあるファイルを除外したいので、trashed = false といったクエリも追加します。クエリパラメーターを複数指定したい場合は and で連結させます。結果として今回のクエリパラメーターは ‘ID’ in parents and trashed = false となります。
上記を踏まえたサンプルスクリプトは以下のとおりです。取得したファイル(フォルダー)の一覧をデータウィンドウにセットする処理となります。
[フォルダー / ファイルの一覧取得] ボタン Clicked イベント
// 変数宣言 Integer li_rtn Integer li_childcount Integer li_index Long ll_root Long ll_files_array Long ll_object String ls_body String ls_id String ls_name String ls_mimeType String ls_kinds OAuthClient loa_client OauthRequest loa_request ResourceResponse lrr_response JsonParser ljp_parser // OAuthClient 作成 loa_client = CREATE OAuthClient // 1. マイドライブの「無題のフォルダー」からフォルダー / ファイルの一覧を取得する(絞り込み:フォルダ ID 且つ ゴミ箱以外にあるファイル(フォルダ)) loa_request.Method = "GET" loa_request.Url = "https://www.googleapis.com/drive/v3/files/?orderBy=folder,name&q='ID' in parents and trashed=false" loa_request.SetAccessToken( is_access_token ) li_rtn = loa_client.RequestResource( loa_request, lrr_response ) IF li_rtn <> 1 THEN // 破棄 DESTROY loa_client // 終了 Return END IF // 2. ファイル(フォルダ)情報を取得する // JsonParser 作成 ljp_parser = CREATE JsonParser // Body データ取得 ls_body = lrr_response.GetHeaders() lrr_response.GetBody( ls_body ) // ルートアイテムのハンドルを取得 ljp_parser.LoadString( ls_body ) ll_root = ljp_parser.GetRootItem() // キー「files」の子項目のハンドルを取得(配列型) ll_files_array = ljp_parser.GetItemArray(ll_root, "files") li_childcount = ljp_parser.GetChildCount(ll_files_array) // 配列の要素内からキー「id」、「name」、「mimeType」がキーとなる値を取得 FOR li_index = 1 TO li_childcount ll_object = ljp_parser.GetChildItem(ll_files_array, li_index) ls_id = ljp_parser.GetItemString(ll_object, "id") ls_name = ljp_parser.GetItemString(ll_object, "name") ls_mimeType = ljp_parser.GetItemString(ll_object, "mimeType") IF ls_mimeType = "application/vnd.google-apps.folder" THEN ls_kinds = "フォルダー" ELSE ls_kinds = "ファイル" END IF dw_1.InsertRow(0) dw_1.SetItem(li_index, "a_col", ls_kinds) dw_1.SetItem(li_index, "b_col", ls_name) dw_1.SetItem(li_index, "c_col", ls_id) NEXT // 破棄 DESTROY ljp_parser // メッセージ MessageBox( "完了", "フォルダー/ファイルの一覧取得に成功しました" ) // 終了 Return
アプリケーションの実行
それではクライマックスです。作成したアプリケーションを実行してみます!画面イメージは以下のようになっています。
最初に [Authorization Code 生成] ボタンをクリックします。するとデフォルト設定されているブラウザーが起動し「Google にログイン(または Google アカウントの選択)」画面が表示されますので、アクセスするGoogle アカウントでログインしてください。
ログインすると “(作成したプロジェクト) が Google アカウントへのアクセスをリクエストしています” と表示されます。 Google アカウントやプロジェクトに問題がないことを確認後、[許可] ボタンをクリックします。
ログイン画面に遷移して画面上にコードが表示されるのでコピーしておきましょう。これが Authorization Code となります。PowerBuilder アプリケーションに戻って、コピーしたコードを Authorization Code のシングルラインエディットに貼り付けて [Access Token 取得] ボタンをクリックします。成功すると「Access Token を取得しました」のメッセージが表示されます。
そして [フォルダー/ファイルの一覧取得] ボタンをクリックします。成功すると取得したフォルダー/ファイルの一覧がアプリケーション上のデータウィンドウに表示されます。ブラウザーで表示したマイドライブにある「無題のフォルダー」の構成と完全一致しているのが確認できます。
まとめ
今回はとてもベーシックですが PowerBuilder から Google ドライブへアクセスしてファイル(フォルダー)の一覧を取得しました。一覧取得以外にもファイル(フォルダー)の作成、コピー、削除、移動、アップロード / ダウンロード、共有 / 共有解除、オーナー変更など様々なリクエストが用意されていますので、今後も Google Drive API の続編としてご紹介できればと思っています。
以上、まさよしでした。