独自のinputタグを使ってレコードへのファイル添付を実現する

概要

kintoneでレコードにファイルを添付するとき、通常はkintone標準のファイル添付フィールドを用います。
この記事では、ファイルを添付フィールドを不可視にして、独自のファイル選択のためのinputタグを配置し、
そこで指定されたファイルを不可視にしていたファイル添付フィールドに関連づける例を紹介します。

フォーム配置

フォームに、ファイル添付フィールドと、inputタグと配置するスペースを配置します。

showイベントで、スペース内に<input type=”text” />を生成します。また、ファイル添付フィールドを不可視にします。


// 要 'jquery';
// 要 '51-modern-default.css'
kintone.app.record.setFieldShown('ファイル添付', false);
let el = kintone.app.record.getSpaceElement('upload-file-space');
$(el).append('<input id="input-file" class="input-file-cybozu" type="file" />');

submitイベントで、指定されたファイルをローカルからFileReaderで読み込み、Blobを生成します。
読み込んだバイナリデータをUnit8ArrayでBlogのコンストラクタに渡すのがポイントです。


// <input type="file" />で指定されたファイルを読み込み、Blobを生成する。
function createPhotoFileBlob(fileElemet) {
  return new kintone.Promise((resolve, reject) => {
    let blob;
    if (typeof(fileElemet.val()) != 'undefined' && fileElemet.val() != "") {
      let fileReader = new FileReader();
      let file = fileElemet[0].files[0];
      fileReader.readAsArrayBuffer(file);
      fileReader.onload = ()=>{
        blob = new Blob([new Uint8Array(fileReader.result)], {
          type: file.type
        });
        return(blob);
      };
    } else {
      return(blob);
    }
  });
}

生成したBlobをkintoneのサーバにアップロードすると、アップロードしたファイル固有のfileKeyを取得することができます。


// kintoneサーバにファイルをアップロードして、fileKeyを取得する。
function uploadFile(fileElemet, blob){
  let formData = new FormData();
  formData.append("__REQUEST_TOKEN__", kintone.getRequestToken());
  formData.append("file", blob, fileElemet.val());

  let xmlHttp = new XMLHttpRequest();
  xmlHttp.open("POST", encodeURI('/k/v1/file.json'), false);
  xmlHttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  xmlHttp.responseType = 'multipart/form-data';
  xmlHttp.send(formData);
  return JSON.parse(xmlHttp.responseText).fileKey;
}

このfileKeyを使って、REST APIで既存レコードの更新や新規レコードの登録を実行します。

よくある質問

一つのfileKeyを複数レコードに使い回せるの?

使いまわせません。更新・追加したいレコードの数だけ、ファイルをアップロードしてfileKeyを取得する必要があります。
ただ、Blobはローカルで持っているデータなので、使いまわすことができます。

submitイベントでevent.record.ファイル添付フィールド.value = fileKeyとしてreturn eventしても反映されない。

そういうものらしいです。なので、以下のようなやり方があります。

fileKey一時保管用のテキストフィールドを新設し。
submitイベントで上記フィールドに、fileKeyを保存。
submit.successイベントでfileKeyを取り出し、kintone apiでレコードを更新。


let record = event.record;
if (record.ファイルキー.value != "") {
    var json = {
        app: kintone.app.getId(),
        id: record.レコード番号.value,
        record: {
            ファイル添付フィールド: {
                value: [{
                fileKey: record.ファイルキー.value
                }]
            }
        }
    };
    return new kintone.Promise((resolve, reject) => {
        kintone.api('/k/v1/record', 'PUT', json,
        (resp)=>{resolve(resp);},
        (error)=>{reject(error)});
    })
    .then((resp)=>{return event;})
    .catch((error)=>{console.log(error);return event;});
} else {
    return event;
}