

Overview
Box: ファイル / フォルダ検索
この工程は、Box の指定フォルダ直下に特定の名前の項目(ファイルやフォルダ)があるかどうか調べます。検索結果のステータスは、FOUND_FILE / FOUND_FOLDER / FOUND_OTHER / NOT_FOUND のいずれかです。
Basic Configs
- 工程名
- メモ
Configs for this Auto Step
- conf_OAuth2
- C1: OAuth2 設定 *
- conf_ParentFolderId
- C2: 検索対象の親フォルダの ID(空白の場合、ルートフォルダ直下を検索します)#{EL}
- conf_Name
- C3: 検索する名前(大文字・小文字は区別されません) *#{EL}
- conf_SearchFolder
- C4: フォルダのみを検索対象にし、見つからなかった場合は異常終了する
- conf_Status
- C5: 検索結果のステータスを保存するデータ項目
- conf_FoundId
- C6: 見つかった項目の ID を保存するデータ項目
- conf_FoundUrl
- C7: 見つかった項目の URL を保存するデータ項目
Notes
- フォルダ ID は、URL に含まれています。https://{sub-domain}.app.box.com/folder/(Folder ID)
- Box のリフレッシュトークンには、期限があります
- 期限を超えないよう、定期的に利用する必要があります (Box: トークンおよびURLの有効期限)
See Also
Script (click to open)
- 次のスクリプトが記述されている XML ファイルをダウンロードできます
- box-file-search.xml (C) Questetra, Inc. (MIT License)
- Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます
const main = () => {
//// == 工程コンフィグの参照 / Config Retrieving ==
const oauth2 = configs.getObject('conf_OAuth2');
const parentFolderId = retrieveParentFolderId();
const name = configs.get('conf_Name');
if (name === '' || name === null) {
throw new Error('Name to search for is blank.');
}
const searchFolderOnly = configs.getObject('conf_SearchFolder');
const statusDef = configs.getObject('conf_Status');
const foundIdDef = configs.getObject('conf_FoundId');
const foundUrlDef = configs.getObject('conf_FoundUrl');
if (statusDef === null && foundIdDef === null && foundUrlDef === null) {
throw new Error('None of the data items to save the result is set.');
}
//// == 演算 / Calculating ==
const {foundId, foundUrl, status} = search(oauth2, parentFolderId, name, searchFolderOnly);
//// == ワークフローデータへの代入 / Data Updating ==
saveData(statusDef, status);
saveData(foundIdDef, foundId);
saveData(foundUrlDef, foundUrl);
};
/**
* config から親フォルダの ID を読み出す(空の場合はルートフォルダの ID "0" を返す)
* @returns {String}
*/
const retrieveParentFolderId = () => {
const confName = 'conf_ParentFolderId';
const parentFolderIdDef = configs.getObject(confName);
let parentFolderId = configs.get(confName);
if (parentFolderIdDef !== null) {
parentFolderId = engine.findData(parentFolderIdDef);
}
if (parentFolderId === '' || parentFolderId === null) {
parentFolderId = '0';
}
return parentFolderId;
};
const STATUS_FOUND_FOLDER = 'FOUND_FOLDER';
const STATUS_FOUND_FILE = 'FOUND_FILE';
const STATUS_FOUND_OTHER = 'FOUND_OTHER';
const STATUS_NOT_FOUND = 'NOT_FOUND';
/**
* 検索する
* 親フォルダ直下の子アイテムを "marker" が無くなるまで(または HTTP リクエスト数の上限に達するまで)ページングしながら走査し、
* 名前が一致するアイテムを探す
* @param {AuthSettingWrapper} oauth2 OAuth2 認証設定
* @param {String} parentFolderId 親フォルダの ID
* @param {String} name 検索する名前
* @param {Boolean} searchFolderOnly フォルダのみを検索対象にし、見つからなかった場合は異常終了する
* @return {Object} result 検索結果 {status, foundId, foundUrl}
*/
const search = (oauth2, parentFolderId, name, searchFolderOnly) => {
const url = `https://api.box.com/2.0/folders/${parentFolderId}/items`;
let marker = '';
const limit = httpClient.getRequestingLimit();
for (let count = 0; count < limit; count++) {
const response = httpClient.begin()
.authSetting(oauth2)
.queryParam('fields', 'id,type,name')
.queryParam('limit', '1000')
.queryParam('usemarker', 'true')
.queryParam('marker', marker)
.get(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status >= 300) {
engine.log(responseStr);
throw new Error(`Failed to search. status: ${status}`);
}
const json = JSON.parse(responseStr);
const items = json.entries || [];
const foundItem = items.find((item) => item.name.toLowerCase() === name.toLowerCase() && (!searchFolderOnly || item.type === 'folder'));
if (foundItem !== undefined) {
return {
status: classify(foundItem),
foundId: foundItem.id,
foundUrl: buildUrl(foundItem)
};
}
marker = json.next_marker;
if (marker === undefined || marker === null || marker === '') {
if (searchFolderOnly) {
throw new Error(`Folder "${name}" was not found.`);
}
// 最終ページまで走査して見つからなかった場合は、正常な検索結果として NOT_FOUND を返す
return { status: STATUS_NOT_FOUND, foundId: null, foundUrl: null };
}
}
throw new Error('Too many files and folders are in the specified folder. The search could not be completed.');
};
/**
* アイテムの type から検索結果ステータスを判定する
* @param {Object} item 名前が一致したアイテム
* @return {String} 検索結果ステータス
*/
const classify = (item) => {
if (item.type === 'folder') {
return STATUS_FOUND_FOLDER;
}
if (item.type === 'file') {
return STATUS_FOUND_FILE;
}
return STATUS_FOUND_OTHER;
};
/**
* アイテムの type と ID から Box の表示 URL を組み立てる
* (file / folder 以外は表示 URL の形式が定まらないため null を返す)
* @param {Object} item 名前が一致したアイテム
* @return {String} 表示 URL(file / folder 以外は null)
*/
const buildUrl = (item) => {
if (item.type === 'folder') {
return `https://app.box.com/folder/${item.id}`;
}
if (item.type === 'file') {
return `https://app.box.com/file/${item.id}`;
}
return null;
};
/**
* データ項目への保存
* @param {ProcessDataDefinitionView} def
* @param {*} data
*/
const saveData = (def, data) => {
if (def === null) {
return;
}
engine.setData(def, data);
};



