🍡

GASでGoogleDrive上のファイルをkintoneにupする

2022/03/12に公開4

GoogleDrive上のファイルをkintoneにアップロードします👀

アプリの準備

↓の記事のようなアプリを準備します。
https://zenn.dev/juridon/articles/bce05edae25e29

必要なフィールドは添付ファイルフィールド!

必要なトークンやらIDやらを集める

fileID

googleDriveのファイルを右クリックして「リンクを取得」
d//viewに挟まれた部分がfileIDです。コピっておきます。
https://drive.google.com/file/d/【ファイルID】/view?usp=sharing

CSRFトークン

↓こちらを参考に
https://developer.cybozu.io/hc/ja/articles/202166310#step4

kintoneのポータルなどで開発ツールを開いて
↓のように入力すると表示されます。

kintone.getRequestToken()

APIトークン

↓こちらを参考に取得してね。レコード追加、レコード編集にもチェックを入れておきましょう。
https://zenn.dev/juridon/articles/8cbd6a2b3c9be9#apiトークンを作っておく

定義しておこう

必要な情報を取り急ぎ定義しておきましょう。

// GoogleDrive にあるファイルを取得
const file = DriveApp.getFileById("【ファイルID】");
// CSRFトークン
const csrfToken = '【CSRFトークン】';
// APIトークン
const apiToken ='【APIトークン】';
// 区切り文字
const boundary = '【とりあえず英数字なら何でも良いとおもう】';
// kintoneのURL
const url = "https://【サブドメイン】.cybozu.com/k/v1/";
// アプリのID
const appId = 485;

ファイルアップロード

アップロード用のfileKeyを取得してから、レコードを追加(または更新)するという2段構えです。
↓これをGASでやります。
https://developer.cybozu.io/hc/ja/articles/201941824

アップロード用fileKeyの取得

アップロード用のfileKeyを取得します。

リクエストボディを作るのがとても大変でした。
↓このあたりを行ったり来たりして作りました🙏

// ★ファイルをアップロードしてfileKeyを取得する
// GoogleDriveのファイルからBlobを取得
const blob = file.getBlob();

// リクエストボディを作る
const bodyText =
  `--${boundary}\r\n
    __REQUEST_TOKEN__:"${csrfToken}"\r\n
    Content-Disposition: form-data; name="file"; filename="${blob.getName()}"\r\n
    Content-Type: ${blob.getContentType()}\r\n\r\n`;
const requestBody = Utilities.newBlob(bodyText).getBytes()
  .concat(blob.getBytes())
  .concat(Utilities.newBlob('\r\n--' + boundary + '--\r\n').getBytes());
const options_file = {
  method: "post",
  contentType: "multipart/form-data; boundary="+boundary,
  payload: requestBody,
  'headers' : {
    'X-Cybozu-API-Token' : apiToken,
  },
};
// fileKeyをゲットする
const resp_file = UrlFetchApp.fetch(url +'file.json',options_file);
const data_file = JSON.parse(resp_file);
const fileKey = data_file.fileKey;

レコードの追加

fileKeyが取得できたら、レコードを追加(または更新)してアップロード完了となります。

  // ★レコードを追加する
  const body = {
    "app": appId,
    "record": {
        "添付ファイル": {
            "value": [
                {
                    "fileKey": fileKey
                }
            ]
        }
    }
  };
  const options_post = {
    "method":"post",
    "contentType":"application/json",
    "headers" : {
      'X-Cybozu-API-Token' : apiToken,
    },
    "payload":  JSON.stringify(body), 
  };
  // レコード追加!
  const resp_post = UrlFetchApp.fetch(url+'record.json',options_post);

コード全体

シングルクォーテーションとダブルクォーテーションが混在していたり、
スペースが空いていたり空いていなかったり、
キャメルケースだったりスネークケースだったり、
ダラっと書いていたりするので

使いたいときは、キレイに書き直して使ってね👀

function GoogleDrive2kintone(){
  // GoogleDrive にあるファイルを取得
  const file = DriveApp.getFileById("【ファイルID】");
  // CSRFトークン
  const csrfToken = '【CSRFトークン】';
  // APIトークン
  const apiToken ='【APIトークン】';
  // 区切り文字
  const boundary = '【とりあえず英数字なら何でも良いとおもう】';
  // kintoneのURL
  const url = "https://【サブドメイン】.cybozu.com/k/v1/";
  // アプリのID
  const appId = 485;

  // ★ファイルをアップロードしてfileKeyを取得する
  // GoogleDriveのファイルからBlobを取得
  const blob = file.getBlob();

  // リクエストボディを作る
  const bodyText =
    `--${boundary}\r\n
      __REQUEST_TOKEN__:"${csrfToken}"\r\n
      Content-Disposition: form-data; name="file"; filename="${blob.getName()}"\r\n
      Content-Type: ${blob.getContentType()}\r\n\r\n`;
  const requestBody = Utilities.newBlob(bodyText).getBytes()
    .concat(blob.getBytes())
    .concat(Utilities.newBlob('\r\n--' + boundary + '--\r\n').getBytes());
  const options_file = {
    method: "post",
    contentType: "multipart/form-data; boundary="+boundary,
    payload: requestBody,
    'headers' : {
      'X-Cybozu-API-Token' : apiToken,
    },
  };
  // fileKeyをゲットする
  const resp_file = UrlFetchApp.fetch(url +'file.json',options_file);
  const data_file = JSON.parse(resp_file);
  const fileKey = data_file.fileKey;
  
  // ★レコードを追加する
  const body = {
    "app": appId,
    "record": {
        "添付ファイル": {
            "value": [
                {
                    "fileKey": fileKey
                }
            ]
        }
    }
  };
  const options_post = {
    "method":"post",
    "contentType":"application/json",
    "headers" : {
      'X-Cybozu-API-Token' : apiToken,
    },
    "payload":  JSON.stringify(body), 
  };
  // レコード追加!
  const resp_post = UrlFetchApp.fetch(url+'record.json',options_post);
}

Discussion

yokotasoyokotaso

記事の執筆ありがとうございます。
2023/11/17時点のkintoneではファイルアップロードに失敗するようです。
おそらく文字列テンプレート内の改行記号とスペースが原因でRFCに準拠しないため、
エラーが帰ってきてしまいます。次のように修正するとファイルアップロードが行えました

少し話は逸れますが、__REQUEST_TOKEN__ は不要と思われます。

@@ -1,6 +1,5 @@
   // リクエストボディを作る
   const bodyText =
-    `--${boundary}\r\n
-      __REQUEST_TOKEN__:"${csrfToken}"\r\n
-      Content-Disposition: form-data; name="file"; filename="${blob.getName()}"\r\n
-      Content-Type: ${blob.getContentType()}\r\n\r\n`;
+    `--${boundary}\r\n` +
+    `Content-Disposition: form-data; name="file"; filename="${blob.getName()}"\r\n` +
+    `Content-Type: ${blob.getContentType()}\r\n\r\n`;
PP

タイムリーな情報、助かりました。ありがとうございます。

TaihongDayeTaihongDaye

急にエラーが出始めて困っていました。
大変助かります。
ありがとうございました。

じゅりどんじゅりどん

yokotaso さん、ありがとうございます!!!!

読者の皆様!
大変申し訳無いのですが、修正する余裕がないので yokotaso さんのコードでなんとかしてください🙏