添付ファイル操作について教えて頂きたいです。

ご覧いただきありがとうございます。

マスタアプリから紐づくレコードを取得してアプリBのテーブルに出力するjavascriptを作成しています。

その中で、添付ファイルの操作で躓いてしまい、お力をお貸し頂ければと存じます。

 

■わからない所

①マスタアプリからダウンロードした添付ファイル情報を抽出してアップロードする部分の記述方法(例など頂けると助かります。)

②添付ファイルをアップロードする際のJSON形式での配列の書き方(for文で回して複数のレコードを取得してきている為、record[i].フィールド名.valueの部分のJSONでの書き方を知りたいです。※iは変数になります。)

 

■ソース

    kintone.events.on([‘app.record.create.submit.success’, ‘app.record.edit.submit.success’], (event2) => {
        var rec2 = event.record;
        var params2 = {
            ‘app’: 5555
        };
        kintone.api(kintone.api.url(‘/k/v1/records’, true), ‘GET’, params2).then(function (resp2) {

            var Allrec2 = resp2.records.length;
            let typeAll2 = new Array();
            for (let s2 = 0; s2 < Allrec2; s2++) {
                typeAll2[s2] = resp2.records[s2].レコードA.value;
            }
            
            for (let i2 = 0; i2 < Allrec2; i2++) {
                let setfk = resp2.records[i2].添付ファイル.value[0];
                if(typeof setfk != ‘undefined’) {
                    
                 let filekey = setfk.fileKey;
                 // 手順1で取得したfileKeyをurlに設定します。
                 let url = kintone.api.urlForGet(‘/k/v1/file’, {fileKey: filekey}, true);

                 // ファイルダウンロードAPI を実行します。
                 let xhr = new XMLHttpRequest();
                 xhr.open(‘GET’, url);
                 xhr.setRequestHeader(‘X-Requested-With’, ‘XMLHttpRequest’);
                 xhr.responseType = ‘blob’;

                 xhr.onload = () => {
                   if (xhr.status === 200) {
                     // success
                     let blob = new Blob([xhr.response]);
                     let windowUrl = window.URL || window.webkitURL;
                     let blobUrl = windowUrl.createObjectURL(blob);
                     console.log(xhr.response.size);
                     console.log(xhr.response.type);
                   } else {
                     // error
                     console.log(xhr.responseText);
                   }
                 };
                 xhr.send();
                 
                 let blobs = new Blob([‘ファイル’], {
                   type: ‘text/plain’
                 });
                 // FormDataにファイルを格納
                 let formData = new FormData();
                 formData.append(‘__REQUEST_TOKEN__’, kintone.getRequestToken());
                 formData.append(‘file’, blobs, ‘test.txt’);//■①個々の書き方がわからないです。
                 
                 let xmlHttp = new XMLHttpRequest();
                 xmlHttp.open(‘POST’, kintone.api.url(‘/k/v1/file’, true), false);
                 xmlHttp.setRequestHeader(‘X-Requested-With’, ‘XMLHttpRequest’);
                 xmlHttp.onload = () => {
                   if (xmlHttp.status === 200) {
                     let key = JSON.parse(xmlHttp.responseText).fileKey;
                     console.log(key);
                      let json = {
                          “appId”: kintone.app.getId(),
                          “recordId”: kintone.app.record.getId(),
                          “record”:{ //■②個々の書き方がわからないです。
                            “必要書類一覧”:{
                                “value”: [{
                                    “0”: [{
                                      “value”: [{
                                        “必要書類一覧_添付ファイル”: [{
                                            “value”:[{fileKey: key}]
                                        }]
                                      }]
                                    }]
                                }]
                            }
                          }
                      };
                   }
                 };
                 xmlHttp.send(formData);
                }
            }
        });
    });

 

 

恐らくこんな処理で可能かと思います。紐づくレコードとありますが、レコード取得のリクエストボディにqueryがないためそのままにしています(そのまま実行するとアプリID5555のレコード100件分の添付ファイルが添付されます)。必要に応じて条件を追加して下さい。

(() => {
    'use strict';

    let subdomain = ''; // サブトメイン
    let fileName = 'test.txt'; // ファイル名

    let fileDownload = (fileKey) => {
        return new Promise((resolve, reject) => {
            let url = `https://${subdomain}.cybozu.com/k/v1/file.json?fileKey=${fileKey}`;
            let xhr = new XMLHttpRequest();

            xhr.open('GET', url);
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.responseType = 'blob';
            xhr.onload = () => {
                if (xhr.status === 200) {
                    resolve(new Blob([xhr.response]));
                } else {
                    reject(new Error(xhr.responseText));
                }
            }
             xhr.send();
         });
    };
    let fileUpload = (blob, fileName) => {
        return new Promise((resolve, reject) => {
            let formData = new FormData();

            formData.append(' __REQUEST_TOKEN__', kintone.getRequestToken());
            formData.append('file', blob, fileName);

            let url = `https://${subdomain}.cybozu.com/k/v1/file.json`;
            let xhr = new XMLHttpRequest();

            xhr.open('POST', url);
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = () => {
                if (xhr.status === 200) {
                    resolve(JSON.parse(xhr.responseText).fileKey);
                } else {
                    reject(new Error(xhr.responseText));
                }
            };
            xhr.send(formData);
        });
    };

    kintone.events.on([
        'app.record.create.submit.success', 'app.record.edit.submit.success'
    ], async (event) => {
        let record = event.record, appId = event.appId, recordId = event.recordId;

        if (record['必要書類一覧'].value[0].value['必要書類一覧_添付ファイル'].value.length) return event;

        let getRecordsParam = {
            app: 5555,
            fields: ['添付ファイル']
        };
        let getRecords = await kintone.api(kintone.api.url('/k/v1/records', true), 'GET', getRecordsParam);

        if (!getRecords.records.length) return event;

        let updateRecordParam = {
            app: appId,
            id: recordId,
            record: {
                '必要書類一覧': {
                    value: record['必要書類一覧'].value
                }
            }
        };
        let fileKeys = [];

        for (let i = 0; i < getRecords.records.length; i++) {
            let getFileKey = getRecords.records[i]['添付ファイル'].value[0]?.fileKey;

            if (!getFileKey) continue;

            let blob = await fileDownload(getFileKey);
            let fileKey = await fileUpload(blob, fileName);

          fileKeys.push({
fileKey: fileKey
});
        };

        updateRecordParam.record['必要書類一覧'].value[0].value['必要書類一覧_添付ファイル'].value = fileKeys;

        let updateRecord = await kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', updateRecordParam);

        return event;
    });
})();

 

わからないところにお答えする前に、非同期処理やPromiseについて理解が必要です(詳細はお調べ下さい)。

>①マスタアプリからダウンロードした添付ファイル情報を抽出してアップロードする部分の記述方法(例など頂けると助かります。)

記載のコードの通りです(XMLで記述しています。openの第三引数をfalseにすれば同期リクエストになるはずですが、敢えてPromiseで記載しています)。

>②添付ファイルをアップロードする際のJSON形式での配列の書き方(for文で回して複数のレコードを取得してきている為、record[i].フィールド名.valueの部分のJSONでの書き方を知りたいです。※iは変数になります。)

前提として、サブテーブルをPUTで更新すると、リクエストボディに記載したサブテーブルの値でそのまま上書きされることになるので、仮に提示されたコードが成功した場合、添付ファイルのみのサブテーブルに書き換えられます(他のフィールドに入力したものは全て削除されます)。これを防ぐためには「既存のサブテーブルと全く同じ値をリクエストボディに含める」か「既存のサブテーブル各行に割り振られているidをリクエストボディに含める」必要があります。

その上で添付ファイルフィールドの配列内に{fileKey: ファイルキー(レコード取得APIで取得したfileKeyを使ってファイルダウンロードAPIを実行し、作成したblobでファイルアップロードAPIを実行し、返り値のfileKey)}と記載していきます。

mls-hashimoto様

アドバイス頂きありがとうございます。

非同期処理とPromiseについて確かにまだ理解が足りないので、調べた上でソースを参考に実装してみます!

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。