Help us understand the problem. What is going on with this article?

GASを使ってGoogle Drive内にあるファイルのダウンロードURLからコンテンツを取得したい

More than 1 year has passed since last update.

概要

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を開いてみると、ログイン画面がダウンロードされていたことが分かります。(下図)

image1.png

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でもいくつか上記に関する質問がありましたので、こちらでもその解決方法について掲載させていただきました。お役に立てましたら幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした