kintone: ファイルアップロード (kintone: Upload File)
kintone アプリのレコード(1件)の添付ファイルフィールドにファイルをアップロード(追加)します。
Configs
  • C1: API トークンを設定した認証設定 *
  • C2: ドメイン(xxxxx.kintone.com または xxxxx.cybozu.com) *
  • C3: ゲストスペース ID(ゲストスペース内のアプリの場合のみ)
  • C4: アプリ ID *
  • C5: レコード ID *
  • C6: 添付ファイルフィールドのフィールドコード *
  • C7: アップロードするファイルが保存されているファイル型データ項目 *
Script (click to open)


main();
function main(){
//// == 工程コンフィグ・ワークフローデータの参照 / Config & Data Retrieving ==
const auth = configs.get("conf_auth");
const domain = configs.get("conf_domain");
const guestSpaceId = configs.get("conf_guestSpaceId");
const appId = configs.get("conf_appId");
const recordId = retrieveRecordId();
const fieldCode = configs.get("conf_fieldCode");
const filesDef = configs.getObject("conf_files");

const apiToken = httpClient.getOAuth2Token( auth );
let files = engine.findData( filesDef );
if (files === null) { // 追加するファイルがない場合は何もせず正常終了
return;
}

//// == 演算 / Calculating ==
checkDomainAndIds( domain, appId, recordId );
const apiUri = determineApiUri( domain, guestSpaceId ); // /v1/ までの URI
const attachments = getAttachmentsInfo( apiUri, apiToken, appId, recordId, fieldCode );
uploadAndAddToAttachments( apiUri, apiToken, files, attachments );
updateAttachmentField( apiUri, apiToken, appId, recordId, fieldCode, attachments );
}

/**
* config からレコード ID を読み出す
* @return {Stromg} recordId レコード ID
*/
function retrieveRecordId() {
const recordIdDef = configs.getObject( "conf_recordId" );
let recordId = configs.get( "conf_recordId" );
if ( recordIdDef !== null ) {
recordId = engine.findData( recordIdDef );
}
return recordId;
}

/**
* ドメイン、アプリ ID、レコード ID が空または不正な文字列であればエラーとする
* @param {String} domain ドメイン
* @param {String} appId アプリ ID
* @param {String} recordId レコード ID
*/
function checkDomainAndIds( domain, appId, recordId ) {
if ( domain === "" || domain === null ) {
throw "Domain is empty.";
}
const reg = new RegExp( '^[0-9a-zA-Z-]{3,32}.(?:kintone.com|cybozu.com)$' );
if ( !reg.test(domain) ) {
throw "Invalid Kintone domain.";
}
if ( appId === "" || appId === null ) {
throw "App ID is empty.";
}
if ( !isValidId(appId) ) {
throw "Invalid App ID.";
}
if ( recordId === "" || recordId === null ) {
throw "Record ID is empty.";
}
if ( !isValidId(recordId) ) {
throw "Invalid Record ID.";
}
}

/**
* ID が有効か(自然数か)を判定する
* @param {String} idString ID の文字列
* @return {Boolean} 有効な ID かどうか
*/
function isValidId( idString ) {
const idReg = new RegExp( '^[1-9][0-9]*$' );
return idReg.test( idString );
}

/**
* kintone REST API の URI を決定する(/v1/ まで)
* ドメインが空、または kintone のドメインとして不正な文字列であればエラーとする
* @param {String} domain ドメイン
* @param {String} guestSpaceId ゲストスペース ID
* @return {String} apiUri API の URI(/v1/ まで)
*/
function determineApiUri( domain, guestSpaceId ) {
let apiUri = "";
if ( guestSpaceId === "" || guestSpaceId === null ) {
apiUri = `https://${domain}/k/v1/`;
} else {
if ( !isValidId(guestSpaceId) ) {
throw "Invalid Guest Space ID.";
}
apiUri = `https://${domain}/k/guest/${guestSpaceId}/v1/`;
}
return apiUri;
}

/**
* kintone REST API にレコード取得の GET リクエストを送信し、添付ファイルの情報の配列を返す
* @param {String} apiUri API の URI(/v1/ まで)
* @param {String} apiToken API トークン
* @param {String} appId アプリ ID
* @param {String} recordId レコード ID
* @param {String} fieldCode 添付ファイルフィールドのフィールドコード
* @return {Array<Object>} attachments 添付ファイル情報 {contentType, fileKey, name, size} の配列
*/
function getAttachmentsInfo( apiUri, apiToken, appId, recordId, fieldCode ) {
const response = httpClient.begin()
.header( "X-Cybozu-API-Token", apiToken )
.queryParam( "app", appId )
.queryParam( "id", recordId )
.get( `${apiUri}record.json` );
//when error thrown
const responseStr = response.getResponseAsString();
const status = response.getStatusCode();
if (status !== 200) {
const accessLog = `---GET request--- ${status}\n${responseStr}\n`;
engine.log(accessLog);
throw `Failed to get record. status: ${status}`;
}
const json = JSON.parse(responseStr);
if ( json.record[fieldCode] === undefined ) { // 一致するフィールドコードがない場合、エラー
throw `${fieldCode} does not exist in the record.`;
}
if ( json.record[fieldCode].type !== "FILE" ) { // 添付ファイルフィールドでない場合、エラー
throw `${fieldCode} is not an Attachment field.`;
}
return json.record[fieldCode].value;
}

/**
* kintone REST API にファイルアップロードの POST リクエストを送信し、ファイル情報の配列を返す
* @param {String} apiUri API の URI(/v1/ まで)
* @param {String} apiToken API トークン
* @param {Array<QfileView>} files アップロードするファイルの配列
* @param {Array<Object>} attachments ファイル情報 {fileKey, etc.} の配列
*/
function uploadAndAddToAttachments( apiUri, apiToken, files, attachments ) {
const fileNum = files.length;
if ( fileNum + 2 > httpClient.getRequestingLimit() ) { // HTTP リクエストの上限を超える場合はエラー
throw "Necessary HTTP requests exceeds the limit.";
}
files.forEach( file => {
const response = uploadFile( apiUri, apiToken, file );
const responseStr = response.getResponseAsString();
const json = JSON.parse(responseStr); // {fileKey}
attachments.push( json );
});
}

/**
* kintone REST API にファイルアップロードの POST リクエストを送信し、レスポンスを返す
* @param {String} apiUri API の URI(/v1/ まで)
* @param {String} apiToken API トークン
* @param {QfileView} file アップロードするファイル
* @return {HttpResponseWrapper} response レスポンス
*/
function uploadFile( apiUri, apiToken, file ) {
const response = httpClient.begin()
.header( "X-Cybozu-API-Token", apiToken )
.multipart( "file", file )
.post( `${apiUri}file.json` );
//when error thrown
const status = response.getStatusCode();
if (status !== 200) {
engine.log(`File Name: ${file.getName()}`);
engine.log(`Content Type: ${file.getContentType()}`);
const responseStr = response.getResponseAsString();
const accessLog = `---POST request--- ${status}\n${responseStr}\n`;
engine.log(accessLog);
throw `Failed to upload file. status: ${status}`;
}
return response;
}

/**
* kintone REST API にレコード更新の PUT リクエストを送信し、添付ファイルフィールドを更新する
* @param {String} apiUri API の URI(/v1/ まで)
* @param {String} apiToken API トークン
* @param {String} appId アプリ ID
* @param {String} recordId レコード ID
* @param {String} fieldCode 添付ファイルフィールドのフィールドコード
* @param {Array<Object>} attachments 添付ファイル情報 {fileKey} の配列
*/
function updateAttachmentField( apiUri, apiToken, appId, recordId, fieldCode, attachments ) {
const body = {
"app": appId,
"id": recordId,
"record": {}
};
body.record[fieldCode] = {
"value": attachments
};
const response = httpClient.begin()
.header( "X-Cybozu-API-Token", apiToken )
.body(JSON.stringify(body), "application/json; charset=UTF-8")
.put( `${apiUri}record.json` );
//when error thrown
const status = response.getStatusCode();
if (status !== 200) {
engine.log(`Request Body: ${JSON.stringify(body)}`);
const responseStr = response.getResponseAsString();
const accessLog = `---PUT request--- ${status}\n${responseStr}\n`;
engine.log(accessLog);
throw `Failed to update record. status: ${status}`;
}
}


Download

2020-11-26 (C) Questetra, Inc. (MIT License)
https://support.questetra.com/ja/addons/kintone-file-upload/
Addonファイルのインポートは Professional もしくは Enterprise でのみご利用いただけます

Notes

  1. API トークンを取得するには、アプリの設定画面の「設定(App Settings)」のタブを開き、「API トークン(API Token)」へと進みます。

    「生成する(Generate)」をクリックし、権限(Permissions)を選択(「レコード編集(Edit records)」権限が必要です)したあと、「保存(Save)」をクリックします。

    「アプリを更新(Update App)」をクリックして変更を適用するのも忘れないようにしてください。
  2. ゲストスペース ID(アプリがゲストスペースにある場合)とアプリ ID は、API トークンの設定画面で確認することができます。

Capture

See also

%d人のブロガーが「いいね」をつけました。