Box: Add Metadata to File

Box: Add Metadata to File

Box: ファイルにメタデータ追加

This item adds metadata to the specified file on Box, using a metadata template defined within your enterprise. An error occurs if the specified metadata template is already added to the file.

Auto Step icon
Basic Configs
Step Name
Note
Configs for this Auto Step
conf_OAuth2
C1: OAuth2 Setting *
conf_FileId
C2: File ID to add metadata to *
conf_TemplateName
C3: Display Name of Metadata Template *
conf_FieldName1
C-K1: Display Name of Field 1
conf_FieldValue1
C-V1: Value for Field 1#{EL}
conf_FieldName2
C-K2: Display Name of Field 2
conf_FieldValue2
C-V2: Value for Field 2#{EL}
conf_FieldName3
C-K3: Display Name of Field 3
conf_FieldValue3
C-V3: Value for Field 3#{EL}
conf_FieldName4
C-K4: Display Name of Field 4
conf_FieldValue4
C-V4: Value for Field 4#{EL}
conf_FieldName5
C-K5: Display Name of Field 5
conf_FieldValue5
C-V5: Value for Field 5#{EL}
conf_FieldName6
C-K6: Display Name of Field 6
conf_FieldValue6
C-V6: Value for Field 6#{EL}
conf_FieldName7
C-K7: Display Name of Field 7
conf_FieldValue7
C-V7: Value for Field 7#{EL}
conf_FieldName8
C-K8: Display Name of Field 8
conf_FieldValue8
C-V8: Value for Field 8#{EL}

Notes

  • The refresh token for Box has an expiration date. Use regularly to ensure that it does not exceed the expiration.
  • To create a metadata template on Box, you have to be a Box administrator. For more details, see the Box support page.
    • Please avoid duplication when naming metadata templates and fields as this item identifies them by their display names.
  • Hidden templates and hidden fields are not supported.
  • Values are to be set in string. The data format of the string is determined by the field type of the metadata.
    • Text: Any string
    • Number: Integer or decimal. Decimal point must be a period (.) and no other delimiters are allowed.
    • Date: yyyy-MM-dd
    • Dropdown – Single Select: An option value
    • Dropdown- Multiple Select: An option value (Multiple select is not supported)

Capture

See also

Script (click to open)
  • An XML file that contains the code below is available to download
    • box-file-metadata-add.xml (C) Questetra, Inc. (MIT License)
    • If you are using Professional, you can modify the contents of this file and use it as your own add-on auto step


const FIELD_NUM = 8; // 扱えるフィールドの数

function main(){
    const oauth2 = configs.getObject("conf_OAuth2");
    const fileId = decideFileId();
    const templateName = configs.get('conf_TemplateName');
    const metadataMap = retrieveMetadataMap();

    const {templateKey, fields} = searchTemplate(oauth2, templateName);
    const metadataObj = buildMetadataObj(metadataMap, fields);
    addMetadata(oauth2, fileId, templateKey, metadataObj);
}

/**
  * ファイル ID を config から読み出す
  * @return {String} fileId ファイル ID
  */
function decideFileId() {
    const fileId = engine.findData(configs.getObject('conf_FileId'));
    if (fileId === '' || fileId === null) {
        throw 'File ID is blank.';
    }
    return fileId;
}

/**
  * メタデータの情報を config から読み出し、Map に格納する
  * @return {Map<String, String>} metadataMap フィールド名と値の Map
  */
function retrieveMetadataMap() {
    const metadataMap = new Map();
    for (let i = 0; i < FIELD_NUM; i++) {
        const fieldName = configs.get(`conf_FieldName${i+1}`);
        const fieldValue = configs.get(`conf_FieldValue${i+1}`);
        if (fieldName === '' || fieldName === null) { // フィールド名が空
            if (fieldValue === '' || fieldValue === null) { // 値も空
                continue;
            }
            throw `Value for Field ${i+1} is set but its display name is blank.`;
        }
        if (fieldValue === '' || fieldValue === null) { // 値が空
            continue;
        }
        if (metadataMap.has(fieldName)) { // フィールド名の指定が重複
            throw `The Field Name "${fieldName}" is set multiple times.`;
        }
        metadataMap.set(fieldName, fieldValue);
    }
    return metadataMap;
}

/**
  * テンプレートを表示名で検索し、一致した非表示でないテンプレートを返す
  * 同名のテンプレートが複数ある場合はエラー
  * @param {AuthSettingWrapper} oauth2  OAuth2 認証設定
  * @param {String} templateName テンプレートの表示名
  * @return {Object} template テンプレートオブジェクト
  */
function searchTemplate(oauth2, templateName) {
    const url = 'https://api.box.com/2.0/metadata_templates/enterprise';
    const response = httpClient.begin()
        .authSetting(oauth2)
        .queryParam('limit', '500') // 現時点で企業内に登録できるテンプレート数は 500 まで
        .get(url);
    const status = response.getStatusCode();
    const responseStr = response.getResponseAsString();
    if (status !== 200) {
        engine.log(responseStr);
        throw `Failed to search template. status:${status}`;
    }
    const {entries} = JSON.parse(responseStr);
    // 名前が一致し、かつ hidden パラメータが false のものを検索
    const result = entries.filter(template => {
        return (template.displayName === templateName) && !template.hidden;
    });
    if (result.length === 0) {
        throw `Template with display name "${templateName}" not found.`;
    }
    if (result.length > 1) {
        throw `Multiple templates with display name "${templateName}" found.`;
    }
    return result[0];
}

/**
  * メタデータオブジェクトを生成する
  * フィールド一覧を表示名で検索し、一致した非表示でないフィールドのキーを使用する
  * 同名のフィールドが複数ある場合はエラー
  * フィールドの型と値の書式が一致しない場合はエラー
  * @param {Map<String, String>} metadataMap フィールド名と値の Map
  * @param {Array<Object>} fields フィールド一覧
  * @return {Object} metadataObj メタデータオブジェクト
  */
function buildMetadataObj(metadataMap, fields) {
    const metadataObj = {};
    metadataMap.forEach((fieldValue, fieldName) => {
        // 名前が一致し、かつ hidden パラメータが false のものを検索
        const result = fields.filter(field => {
            return (field.displayName === fieldName) && !field.hidden;
        });
        if (result.length === 0) {
            throw `Field with display name "${fieldName}" not found.`;
        }
        if (result.length > 1) {
            throw `Multiple fields with display name "${fieldName}" found.`;
        }
        const field = result[0];
        let value = fieldValue;
        // フィールドの型とデータ項目の型の一致を確認し、値を整形する
        switch (field.type) {
            case 'string':
                break;
            case 'float':
                value = checkAndParseFloat(fieldName, value);
                break;
            case 'date':
                value = checkAndParseDate(fieldName, value);
                break;
            case 'enum':
                checkOptions(fieldName, value, field.options);
                break;
            case 'multiSelect': // 1 つだけ選択する場合にのみ対応
                checkOptions(fieldName, value, field.options);
                value = Array.of(value);
                break;
             default: // 現状はありえないが、Box のメタデータのフィールド型が追加された場合に発生
                throw `The type of "${fieldName}" is not supported: ${field.type}`;
        }
        // オブジェクトに追加
        metadataObj[field.key] = value;
    });
    return metadataObj;
}

/**
  * 文字列を数値に変換
  * マイナス記号と小数点以外の文字が含まれる場合はエラー
  * @param {String} fieldName フィールド名(エラー出力用)
  * @param {String} value 入力文字列
  * @return {Number} parsedValue 数値
  */
function checkAndParseFloat(fieldName, value) {
    const regex = /^\-?(\d|[1-9]\d+)(\.\d+)?$/;
    if (!regex.test(value)) {
        throw `The type of "${fieldName}" is float, but the value "${value}" is invalid as float.`;
    }
    // 文字列を float にパース
    return parseFloat(value);
}

/**
  * 文字列を yyyy-MM-dd'T'HH:mm:ssZ 形式の文字列に変換
  * 入力が yyyy-MM-dd 形式の日付でない場合はエラー
  * @param {String} fieldName フィールド名(エラー出力用)
  * @param {String} value 入力文字列
  * @return {String} parsedValue 指定形式の文字列
  */
function checkAndParseDate(fieldName, value) {
    const regex = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
    const matched = value.match(regex);
    if (matched === null) { // yyyy-MM-dd 形式でない
        throw `The type of "${fieldName}" is date, but the value "${value}" is not in the format of "yyyy-MM-dd".`;
    }
    // 日付として不正でないかをチェック
    // Date にパースするだけでは6月31日なども許可されてしまうので、年月日それぞれをチェック
    const y = parseInt(matched[1]);
    const m = parseInt(matched[2]) -1;
    const d  = parseInt(matched[3]);
    const date = new Date(y, m, d);
    if (y !== date.getFullYear() || m !== date.getMonth() || d !== date.getDate()) {
        throw `The type of "${fieldName}" is date, but the value "${value}" is invalid as date.`;
    }
    return `${value}T00:00:00Z`;
}

/**
  * 入力文字列が選択肢として存在するかチェックし、存在しない場合はエラー
  * 選択肢の表示名(キー)が重複することは、Box の仕様としてありえない
  * @param {String} fieldName フィールド名(エラー出力用)
  * @param {String} value 入力文字列
  * @param {Array<Object>} options 選択肢一覧
  */
function checkOptions(fieldName, value, options) {
    if (!options.some(option => option.key === value)) {
        throw `The value "${value}" is not in the options of the field "${fieldName}".`;
    }
}

/**
  * メタデータを追加
  * @param {AuthSettingWrapper} oauth2  OAuth2 認証設定
  * @param {String} fileId ファイル ID
  * @param {String} templateKey テンプレートキー
  * @param {Object} metadataObj 追加するメタデータ
  */
function addMetadata(oauth2, fileId, templateKey, metadataObj) {
    const url = `https://api.box.com/2.0/files/${encodeURIComponent(fileId)}/metadata/enterprise/${encodeURIComponent(templateKey)}`;
    const response = httpClient.begin()
        .authSetting(oauth2)
        .body(JSON.stringify(metadataObj), 'application/json; charset=UTF-8')
        .post(url);
    const status = response.getStatusCode();
    if (status !== 201) {
        engine.log(response.getResponseAsString());
        throw `Failed to add metadata. status:${status}`;
    }
}

    
Scroll to Top

Discover more from Questetra Support

Subscribe now to keep reading and get access to the full archive.

Continue reading