Google Drive API で Google ドライブへアクセス

Google ドライブへアクセス

こんにちは、サポート部のまさよしです。

早いもので Google API シリーズも今回で第 5 弾となります。今まで紹介したシリーズについては以下にリンクを貼りましたので、ご興味ある方は是非あわせてご一読ください!

そして今回は、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 シリーズで変わる部分は 56 となります。

  • Google Cloud Platform にログイン後、プロジェクトを作成して Google Drive API を有効にします
    • ナビゲーション メニューから「IAM と管理」-「リソースの管理」をクリック
    • リソースの管理画面で「プロジェクトを作成」をクリック
    • 新しいプロジェクト画面でプロジェクト名を入力し [作成] ボタンをクリック
    • 作成したプロジェクトがドロップダウンで選択されているのを確認後、ナビゲーション メニューから「API とサービス」-「ライブラリ」をクリック
    • API ライブラリ画面で表示されている Google Workspace カテゴリから Google Drive API を選択
    • Google Drive API 画面の[有効にする] ボタンをクリック
    API ライブラリ画面

    API ライブラリ画面

  • 有効にした Google Drive API の認証情報を設定します
    • ナビゲーション メニューから「API とサービス」-「認証情報」をクリック
    • 認証情報画面で「認証情報を作成」をクリック後、「OAuth クライアント ID」をクリック
    • OAuth クライアント ID の作成画面でアプリケーションの種類の選択や OAuth クライアントの名前を入力後、[作成] ボタンをクリック

作成が無事終わるとクライアント IDクライアント シークレットが表示されます。クライアント ID とクライアント シークレットは PowerBuilder 内の処理で使用するので、忘れないようテキストで保存 or メモしておいてください。仮に忘れてしまった場合、認証情報画面の OAuth 2.0 クライアント ID リストから OAuth クライアントの名前をクリックすれば再表示できますので、ご安心を!

認証情報画面  

認証情報画面

  OAuth クライアント作成完了画面   

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 Drive のマイドライブ

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

アプリケーションの実行

それではクライマックスです。作成したアプリケーションを実行してみます!画面イメージは以下のようになっています。

Google Drive アクセスアプリ

最初に [Authorization Code 生成] ボタンをクリックします。するとデフォルト設定されているブラウザーが起動し「Google にログイン(または Google アカウントの選択)」画面が表示されますので、アクセスするGoogle アカウントでログインしてください。

ログインすると “(作成したプロジェクト) が Google アカウントへのアクセスをリクエストしています” と表示されます。 Google アカウントやプロジェクトに問題がないことを確認後、[許可] ボタンをクリックします。

Authorization Code取得

 

 

 

ログイン画面に遷移して画面上にコードが表示されるのでコピーしておきましょう。これが Authorization Code となります。PowerBuilder アプリケーションに戻って、コピーしたコードを Authorization Code のシングルラインエディットに貼り付けて [Access Token 取得] ボタンをクリックします。成功すると「Access Token を取得しました」のメッセージが表示されます。

そして [フォルダー/ファイルの一覧取得] ボタンをクリックします。成功すると取得したフォルダー/ファイルの一覧がアプリケーション上のデータウィンドウに表示されます。ブラウザーで表示したマイドライブにある「無題のフォルダー」の構成と完全一致しているのが確認できます。

マイドライブ 取得

まとめ

今回はとてもベーシックですが PowerBuilder から Google ドライブへアクセスしてファイル(フォルダー)の一覧を取得しました。一覧取得以外にもファイル(フォルダー)の作成、コピー、削除、移動、アップロード / ダウンロード、共有 / 共有解除、オーナー変更など様々なリクエストが用意されていますので、今後も Google Drive API の続編としてご紹介できればと思っています。

以上、まさよしでした。

テクニカルブログ 一覧を見る
PowerBuilder マイグレーション
PowerBuilder 2019 R3 日本語版リリース 紹介動画