概要
Google Apps Script(GAS)を使ってGoogle Drive内にあるファイルのダウンロードURLからコンテンツを取得するための方法について記載します。
問題点
Googleの拡張サービスDrive.Files.get()
を使用した際のexportLinks
や、DriveAppでのgetDownloadUrl()
で得られるURLはGoogleにログインしている状態でアクセスすることでファイルのダウンロードができます。しかし、GASを使ってUrlFetchApp.fetch(url)
によりそれらのURLからファイルをダウンロードしようとすると、下記のようにファイルそのものではなくHTMLが取得されたり、あるいはエラーが発生してしまいます。
Drive.Files.get()の場合
例えばGoogle DocsをダウンロードしてそのBlobを取得しようと以下のようなスクリプトを用いると、ファイルは作成されますが、中身はHTMLになってしまいます。
var url = Drive.Files.get("### file ID ###").exportLinks["application/pdf"];
var blob = UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getBlob();
DriveApp.createFile(blob.setName("sample"));
この作成されたHTMLを開いてみると、ログイン画面がダウンロードされていたことが分かります。(下図)
DriveApp.getFileById()の場合
Google Docs以外であれば下記のようなスクリプトでもダウンロードURLを取得することができます。
var url = DriveApp.getFileById("### file ID ###").getDownloadUrl();
var res = UrlFetchApp.fetch(url).getBlob(); // ← ここでエラーが発生する
DriveApp.createFile(blob.setName("sample"));
この場合、下記のようなエラーが発生します。
https://doc-04-2k-docs.googleusercontent.com/docs/securesc/#####?e=download&gd=true に対するリクエストが失敗し、コード 401 が返されました
上記はいずれもスクリプト実行時に認証をしていないために目的のコンテンツが取得できないと考えられます。
解決方法
そこで、スクリプト実行時、すなわち、UrlFetchApp.fetch()
を実行する際に認証できるようにします。
アクセストークンをクエリパラメータとしてダウンロードURLに追加します。
実際は"&access_token=" + ScriptApp.getOAuthToken()
をダウンロードURLに追加します。内容はScriptApp.getOAuthToken()
を使ってアクセストークンを発行し、access_token
をキーとして追加します。アクセストークンを発行するScriptApp.getOAuthToken()
はなかなか便利で、一般的なスコープを自動で割り当ててくれます。これによりスクリプト実行時に認証が行われ、ダウンロードURLを使ってGoogle Drive内にあるコンテンツをダウンロードすることができるようになり、スクリプトでダウンロードしたコンテンツをBlobとして扱うことができるようになります。いろいろな応用が期待できます。
上記問題点で使用したサンプルスクリプトを修正したものは下記の通りです。
サンプル 1
var url = Drive.Files.get("### file ID ###").exportLinks["application/pdf"] + "&access_token=" + ScriptApp.getOAuthToken();
var blob = UrlFetchApp.fetch(url, {muteHttpExceptions: true}).getBlob();
DriveApp.createFile(blob.setName("sample"));
サンプル 2
var url = DriveApp.getFileById("### file ID ###").getDownloadUrl() + "&access_token=" + ScriptApp.getOAuthToken();
var res = UrlFetchApp.fetch(url).getBlob();
DriveApp.createFile(blob.setName("sample"));
これらのサンプルスクリプトは、ダウンロードURLから取得したコンテンツのBlobを使ってファイルが作成されます。
Stackoverflowでもいくつか上記に関する質問がありましたので、こちらでもその解決方法について掲載させていただきました。お役に立てましたら幸いです。