
Box: Download File as PDF/Text/Image
This item downloads the specified file on Box in the specified file format.
Basic Configs
- Step Name
- Note
Configs for this Auto Step
- conf_OAuth2
- C1: OAuth2 Setting *
- conf_FileId
- C2: File ID to download *
- conf_Representation
- C3: File Format in which to download the file *
- conf_FileName
- C4: File Name (named with the file name on Box if blank)#{EL}
- conf_Files
- C5: File type data item to add the downloaded file *
- conf_urlTemplate
- C6: Data item to store temporary data required for download *
Notes
- The refresh token for Box has an expiration date. Use regularly to ensure that it does not exceed the expiration.
- This item uses Box file representation API. For supported file types, see the Box Developer Documentation.
- For some file formats like JPEG (2048×2048), PNG (1024×1024) and PNG (2048×2048), each page of the original file will be downloaded as a separate file. The downloaded files will have a page number attached at the beginning of their file names.
Capture

See also
Script (click to open)
- An XML file that contains the code below is available to download
- box-file-representation-download.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 PATH_VARIABLE = "{+asset_path}";
function main() {
const oauth2 = configs.get('conf_OAuth2');
const fileId = decideFileId();
const representation = configs.get('conf_Representation');
const urlDef = configs.getObject("conf_urlTemplate");
const {urlTemplate, paged} = getRepresentationInfo(oauth2, fileId, representation);
let url;
if (paged !== 'true') { // ページ分割されていない場合
url = urlTemplate.replace(PATH_VARIABLE, '');
} else {
url = urlTemplate;
}
engine.setData(urlDef, url);
return false;
}
function proceed() {
const oauth2 = configs.get('conf_OAuth2');
const representation = configs.get('conf_Representation');
const fileName = configs.get('conf_FileName');
const urlDef = configs.getObject("conf_urlTemplate");
const fileDef = configs.getObject("conf_Files");
const url = engine.findData(urlDef);
let qfiles;
if (url.includes(PATH_VARIABLE)) {
// ページ割されている場合
qfiles = downloadPages(oauth2, url, representation, fileName);
} else {
// ページ割されていない場合
qfiles = download(oauth2, url, representation, fileName);
}
if (qfiles === false) {
return false;
}
saveFiles(fileDef, qfiles);
engine.setData(urlDef, null);
}
/**
* ファイル 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;
}
/**
* レプリゼンテーションの情報を取得する GET リクエストを送信
* @param {String} oauth2 OAuth2 設定
* @param {String} fileId ファイル ID
* @param {String} representation レプリゼンテーション
* @return {Object} representationInfo
* @return {String} representationInfo.urlTemplate ダウンロードの際の URL テンプレート
* @return {String|undefined} representationInfo.paged ページ割されているかどうか
*/
function getRepresentationInfo(oauth2, fileId, representation) {
const url = `https://api.box.com/2.0/files/${encodeURIComponent(fileId)}`;
const response = httpClient.begin()
.authSetting(oauth2)
.queryParam('fields', 'representations')
.header('X-REP-HINTS', representation)
.get(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 200) {
engine.log(responseStr);
throw `Failed to get representations. status:${status}`;
}
const {entries} = JSON.parse(responseStr).representations;
if (entries.length === 0) {
throw `The ${representation} representation is unavailable for this file.`;
}
const urlTemplate = entries[0].content.url_template;
const paged = entries[0].properties.paged; // "true", "false" or undefined
return {urlTemplate, paged};
}
/**
* レプリゼンテーションをダウンロードする GET リクエストを送信
* ページ割されていない場合
* @param {String} oauth2 OAuth2 設定
* @param {String} url URL
* @param {String} representation レプリゼンテーション
* @param {String} fileName ファイル名
* @return {Array<NewQfile>} qfiles ダウンロードしたファイルを格納した配列
*/
function download(oauth2, url, representation, fileName) {
const response = httpClient.begin()
.authSetting(oauth2)
.queryParam('set_content_disposition_type', 'attachment')
.get(url);
const status = response.getStatusCode();
if (status === 202) { // レプリゼンテーション作成中でダウンロードできない
return false;
}
if (status !== 200) { // その他のエラー
engine.log(response.getResponseAsString());
throw `Failed to download the representation ${representation}. status:${status}`;
}
const contentType = response.getContentType();
const content = response.getResponse();
const fileNameToSet = decideFileNameToSet(fileName, response);
const qfile = new com.questetra.bpms.core.event.scripttask.NewQfile(
fileNameToSet, contentType, content
);
return [qfile];
}
/**
* レプリゼンテーションをダウンロードする GET リクエストを送信
* ページ割されている場合
* @param {String} oauth2 OAuth2 設定
* @param {String} urlTemplate URL テンプレート
* @param {String} representation レプリゼンテーション
* @param {String} fileName ファイル名
* @return {Array<NewQfile>} qfiles ダウンロードしたファイルを格納した配列
*/
function downloadPages(oauth2, urlTemplate, representation, fileName) {
const extension = representation.substring(1, 4); // jpg or png
const qfiles = [];
const httpLimit = httpClient.getRequestingLimit();
for (let pageNum = 1; ; pageNum++) {
if (pageNum > httpLimit) {
throw 'Number of necessary HTTP requests exceeds the limit.';
}
const url = urlTemplate.replace('{+asset_path}', `${pageNum}.${extension}`);
engine.log(`url: ${url}`);
const response = httpClient.begin()
.authSetting(oauth2)
.queryParam('set_content_disposition_type', 'attachment')
.get(url);
const status = response.getStatusCode();
if (pageNum === 1 && status === 202) { // レプリゼンテーション作成中でダウンロードできない
//throw `The representation ${representation} is being created and not available yet. Please try again later.`;
return false;
}
if (pageNum > 1 && status === 404) { // ページを最後までダウンロードした。ループから抜ける
break;
}
if (status !== 200) { // その他のエラー
engine.log(response.getResponseAsString());
throw `Failed to download the page ${pageNum} of the representation ${representation}. status:${status}`;
}
const contentType = response.getContentType();
const content = response.getResponse();
let fileNameToSet = decideFileNameToSet(fileName, response);
fileNameToSet = `${pageNum}-${fileNameToSet}`; // ファイル名にページ番号を追加
const qfile = new com.questetra.bpms.core.event.scripttask.NewQfile(
fileNameToSet, contentType, content
);
qfiles.push(qfile);
}
return qfiles;
}
/**
* 保存時のファイル名を決定する
* @param {String} fileName 新しく名前をつける場合のファイル名
* @param {HttpResponseWrapper} response ファイルダウンロードのレスポンス
* @return {String} fileNameToSet 設定するファイル名
*/
function decideFileNameToSet(fileName, response) {
if (fileName !== '' && fileName !== null) {
return fileName;
}
// ファイル名をレスポンスの Content-Disposition ヘッダから取得する
const contentDisposition = response.getHeaderValues('Content-Disposition')[0];
const matched = contentDisposition.match(/filename\*=UTF-8''(.+)/);
return decodeURI(matched[1]);
}
/**
* 複数のファイルを追加保存する
* @param {ProcessDataDefinitionView} fileDef 保存先データ項目
* @param {Array<NewQfile>} qfiles 追加保存するファイルを格納した配列
*/
function saveFiles(fileDef, qfiles) {
let files = engine.findData(fileDef);
if (files === null) {
files = new java.util.ArrayList();
}
qfiles.forEach(qfile => {
files.add(qfile);
});
engine.setData(fileDef, files);
}