別ドメインの kintone にファイルアップロード(kintone JavaScript API)
はじめに
kintone.proxy.upload() を利用して別ドメインにファイルをアップロードするコードのメモです。
ポイントは次の 2 つです。
- kintone.proxy.upload() に渡す data.value には Blob 型を指定する
- ファイルアップロード API は multipart/form-data 形式のみを受け付ける
const downloadFile = async ({ fileKey }) => { const url = `/k/v1/file.json?fileKey=${fileKey}`; const headers = { "X-Requested-With": "XMLHttpRequest" }; // ファイルダウンロードは kintone.api() では実行できない const res = await fetch(url, { headers }); return res.arrayBuffer();};
const stringToArrayBuffer = (string) => { const arrayBuffer = new ArrayBuffer(string.length); const uint8 = new Uint8Array(arrayBuffer); return uint8.map((_, i) => string.charCodeAt(i)).buffer;};
const mergeArrayBuffer = (ab1, ab2) => { const uint8 = new Uint8Array(ab1.byteLength + ab2.byteLength); uint8.set(new Uint8Array(ab1), 0); uint8.set(new Uint8Array(ab2), ab1.byteLength); return uint8.buffer;};
const getPostData = ({ boundary, body, filename }) => { let headerString = ""; headerString += `--${boundary}\r\n`; headerString += `Content-Disposition: form-data; name="file"; filename="${filename}"\r\n`; headerString += "Content-Type: application/octet-stream\r\n"; headerString += "\r\n";
let footerString = ""; footerString += "\r\n"; footerString += `--${boundary}--`;
const header = stringToArrayBuffer(headerString); const footer = stringToArrayBuffer(footerString);
return [header, body, footer].reduce((ac, cu) => mergeArrayBuffer(ac, cu));};
kintone.events.on("app.record.index.show", async (event) => { // 登録先のドメインとAPIトークン const domain = "xxx.cybozu.com"; const apiToken = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
// 登録元のファイル情報 const downloadFileKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const filename = "xxxxx.xxx"; // 例)sample.png
const boundary = "boundary"; const body = await downloadFile({ fileKey: downloadFileKey }); const arrayBuffer = getPostData({ boundary, body, filename });
const url = `https://${domain}/k/v1/file.json`; const params = { "X-Cybozu-API-Token": apiToken, "Content-Type": `multipart/form-data; boundary=${boundary}`, }; const data = { format: "RAW", value: new Blob([arrayBuffer]) };
try { const res = await kintone.proxy.upload(url, "POST", params, data); const { fileKey } = JSON.parse(res[0]); } catch (error) { console.error(error); }
return event;});