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);
const getPostData = ({ boundary, body, filename }) => {
headerString += `--${boundary}\r\n`;
headerString += `Content-Disposition: form-data; name="file"; filename="${filename}"\r\n`;
headerString += "Content-Type: application/octet-stream\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) => {
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`;
"X-Cybozu-API-Token": apiToken,
"Content-Type": `multipart/form-data; boundary=${boundary}`,
const data = { format: "RAW", value: new Blob([arrayBuffer]) };
const res = await kintone.proxy.upload(url, "POST", params, data);
const { fileKey } = JSON.parse(res[0]);