LoginSignup
2

More than 3 years have passed since last update.

Google Apps Scriptを使ってmultipart/form-dataタイプでHTTPリクエストする

Posted at

背景

先日、Google Apps ScriptのUrlFetchAppを使ってmultipart/form-dataタイプでファイルをやり取りする状況が発生しました。オフィシャルドキュメントでは、payloadにオブジェクトを与えると自動でapplication/x-www-form-urlencodedまたはmultipart/form-dataとしてリクエストされるとありましたが、残念ながら今回の用途には使用できませんでした。また、Javascriptのfetchで使用するForm​Data()のようなサンプルがあればと探しましたが残念ながら見つからず、丁度いくつかのアプリで使用する予定もありましたのでライブラリとして作成しました。リポジトリはこちらです。

ライブラリのプロジェクトキー

1sm9V-w8-0i3U4-10N6XyaRjHk5voiuJ1ArKSLo3htOUasB6GcPcIq8Kb

インストール方法

  1. 最初にスクリプトディタを立ち上げてライブラリをインストールします。インストール方法はこちらをご覧ください。
    • このとき使用するライブラリのプロジェクトキーは、1sm9V-w8-0i3U4-10N6XyaRjHk5voiuJ1ArKSLo3htOUasB6GcPcIq8Kbです。

使い方

使用方法は、サンプルスクリプトをご覧頂く方が分かりやすいのではないかと思いましたので、サンプルスクリプトを使用します。

サンプルスクリプト 1

このスクリプトでは、単体のリクエストを実行しています。基本はUrlFetchApp.fetch()と同じですが、formDataを与えるbodyのプロパティを追加しています。

スクリプトの動作内容

Drive API v3を使用してPDFファイルあるいは画像ファイルをOCRを行いGoogle Documentに変換します。

スクリプト

function sample1() {
  var fileId = "### fileId of PDF ###";
  var metadata = {
    name: "sampleDocument", // Filename of created Google Document
    mimeType: MimeType.GOOGLE_DOCS // MimeType of Google Document
  };
  var fileBlob = DriveApp.getFileById(fileId).getBlob();
  var form = FetchApp.createFormData(); // Create form data
  form.append(
    "metadata",
    Utilities.newBlob(JSON.stringify(metadata), "application/json")
  );
  form.append("file", fileBlob);
  var url =
    "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart";
  var params = {
    method: "POST",
    headers: { Authorization: "Bearer " + ScriptApp.getOAuthToken() },
    body: form
  };
  var res = FetchApp.fetch(url, params);
  Logger.log(res);
  // DriveApp.createFile(blob) // This comment line is used for automatically detecting scope for running this sample script.
}

サンプルスクリプト 2

このスクリプトでは、複数のリクエストを一度に実行しています。基本はUrlFetchApp.fetchAll()と同じですが、formDataを与えるbodyのプロパティを追加しています。

スクリプトの動作内容

Drive API v3を使用してテキストファイルを既存のGoogle Documentに上書きします。リクエスト自体は非同期で実行されます。Drive APIを用いたファイルのアップデートはバッチリクエストでは実行できないことを考えると、下記のようなスクリプトはAPI使用回数はリクエスト数と同数にはなりますが、現状の一つの回避策になるかもしれません。

スクリプト

function sample2() {
  var contents = [
    {
      fileName: "newFilename1", // new filename
      docs: "### GoogleDocumentId1 ###", // Destination fileId of existing Google Document.
      textFile: "### textFileId1 ###" // Source fileId of text file.
    },
    {
      fileName: "newFilename2",
      docs: "### GoogleDocumentId2 ###",
      textFile: "### textFileId2 ###"
    }
  ];
  var accessToken = ScriptApp.getOAuthToken();
  var requests = contents.map(function(e) {
    var metadata = { name: e.fileName };
    var form = FetchApp.createFormData(); // Create form data
    form.append(
      "metadata",
      Utilities.newBlob(JSON.stringify(metadata), "application/json")
    );
    form.append("file", DriveApp.getFileById(e.textFile).getBlob());
    var url =
      "https://www.googleapis.com/upload/drive/v3/files/" +
      e.docs +
      "?uploadType=multipart";
    params = {
      url: url,
      method: "PATCH",
      headers: { Authorization: "Bearer " + accessToken },
      body: form
    };
    return params;
  });
  var res = FetchApp.fetchAll(requests);
  Logger.log(res);
  // DriveApp.createFile(blob) // This comment line is used for automatically detecting scope for running this sample script.
}

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2