2022-11-21
(C) Questetra, Inc. (MIT License)
2
This item uploads files to the specified folder on Box.
この工程は、Box の指定フォルダにファイルをアップロードします。
https://support.questetra.com/bpmn-icons/box-upload/
https://support.questetra.com/ja/bpmn-icons/box-upload/
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAD/UlEQVRYR82XbWibVRTHf/fJ2jXJ
2qSd65x11aC0YgJWZUwEWZ0D/SJaHYKKmgykbL70Bf2k4IYwZOKWOhFRMM9QZxHUjSEo+7AOlA1E
7WSRThzdqq1tWWxjm7Zrk1y5N+SlydM2XdvN50sebs5z7u+e8z/n3iu4xo9Y1Pz+3x6F5BagAYQb
oX4BSTfIUaAbIboIeY8W63dhAH+vGyZaQLYihLsox1LBiCA4OjA9CmzOZ34Af9gP8kDRE+dPo0GM
AObtR+YimBvAfzaIEC1FrXghIymDmL42KzNrgMBZE8RzC/ld1P8SE9MbyP+mEGA5V16Ykg5MX2vu
8GwAlXNBaFErW6yxFE25msgCaLXHeq9YcMWCaGE6PenqyAEI70bwRrF+lmQn2YPp3a18ZAECYVWv
rrTj0I4bqHLaeOTgn0uay/JjFQXTV5kFUB1OyK9zjYeC9ThKBeW7epYfQHfPlBZSEbBQ/nBHCmDN
zpUCkLoiUgCBcBegenzmUQDO1QaHT0dpqC3T4yd7YrzyxZB+33V/Jds3VbBmtUH/SJzmQwN07ryR
7r4p2jtTNh88uwHPdaU8uP+iVRRPEvI2pgEuADflA6wrtxV8+GPvJBcuzfDY3RXYjBzgfxNU2A0M
AW2fD1Jht/FmUzWx6STuFyyiqDYw03tnGkDmz6QioADUZO98F8HtMHh521o9lpQwNSMxvx/l9PkJ
XtpWxSaPnZFYArfDRmQ8oeFcDhvvHv+Hts5Bax2FvGJeAFUFW97q5Yc/JrWDVx9ay74n1uv3Iz+P
0fRetkIiB+uxlxj80jfFvbfatc2Jnhhb91mGPwWUA1CQgoH9dawrX0VN+zmGxxLa/qnNLj5rrtHv
ShtPf9ifWdnfB+p02X7z6zhNd5Xr8U9PRXnmo6zN7DDIM4R8DXOK8NRrHu65xY7K+QNvX2SDaxXH
Wmqpu75U+1FhVsL78qcxDjfX8ORml05BeZmN6YTUDUalQenh/RMjC4jQogwb6x189eJGKp02YpeT
2AxBWYmgLzLDwGhcw8UTaJG57AaT0xIlJGXTcTyi09HcWMml8QTVLecKAWRuGVo0IvXF1tuc7N1e
rUspnpSE+y+z4+N+/hqJ88nzNdxX58BRajAYjbPn6DB7H1/P70PTPNzRpyf8tr2WjVUleF8/bwGQ
24jU33mt2Fq2yzYaJeTVx7v/0WaktmMxoaohsyEt23pnO4oiHTcXbsfK6JoeSNKUK3oky54D0tNd
vUMp8hAhnz8/rVfpWF648vkjkEmHPqiYSxBmFCn8V3YxyUDoq1krAnWcLrZCokjU1Sy4tKtZfsJS
l9NGhGgA6QZxR8pEngExipTdYHTNt+LiNbBCTSDf7X8FbX8wYecpbwAAAABJRU5ErkJggg==
{
configs.put('conf_OAuth2', 'Box');
const fileDef = engine.createDataDefinition('ファイル', 1, 'q_files', 'FILE');
configs.putObject('uploadedFile', fileDef);
engine.setData(fileDef, files);
configs.put('uploadedFolderId', folderId);
const idDef = engine.createDataDefinition('ファイルID', 2, 'q_ids', 'STRING_TEXTAREA');
configs.putObject('fileId', idDef);
engine.setData(idDef, '事前文字列');
const urlDef = engine.createDataDefinition('ファイルURL', 3, 'q_urls', 'STRING_TEXTAREA');
configs.putObject('fileUrl', urlDef);
engine.setData(urlDef, '事前文字列');
return {
fileDef,
idDef,
urlDef
};
};
/**
* 指定サイズのテキストファイルを作成
* @param name
* @param size
* @return qfile
*/
const createQfile = (name, size) => {
let text = '';
if (size >= 4000) {
text = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.repeat(100); // 40 * 100 = 4000
}
while (text.length < size) {
if (text.length !== 0 && text.length * 2 <= size) {
text += text;
} else if (text.length + 1000 <= size) {
text += 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'.repeat(25); // 40 * 25 = 1000
} else {
text += 'a';
}
}
return engine.createQfile(name, 'text/plain; charset=US-ASCII', text);
};
test('File is null', () => {
const {
idDef,
urlDef
} = prepareConfigs(configs, null, '');
execute();
expect(engine.findData(idDef)).toEqual('');
expect(engine.findData(urlDef)).toEqual('');
});
test('File Count > requestingLimit', () => {
const files = new java.util.ArrayList();
while (files.size() <= httpClient.getRequestingLimit()) {
files.add(createQfile('テスト', 0));
}
prepareConfigs(configs, files, '');
expect(execute).toThrow('Number of requests is over the limit');
});
test('File Name contains /', () => {
const files = new java.util.ArrayList();
files.add(createQfile('テスト', 0));
files.add(createQfile('テスト/テスト', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Invalid File Name');
});
test('File Name contains \\', () => {
const files = new java.util.ArrayList();
files.add(createQfile('テスト', 0));
files.add(createQfile('テスト\\テスト', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Invalid File Name');
});
test('File Name starts with space', () => {
const files = new java.util.ArrayList();
files.add(createQfile('テスト', 0));
files.add(createQfile(' test', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Invalid File Name');
});
test('File Name ends with space', () => {
const files = new java.util.ArrayList();
files.add(createQfile('テスト', 0));
files.add(createQfile('test ', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Invalid File Name');
});
test('File Name is .', () => {
const files = new java.util.ArrayList();
files.add(createQfile('テスト', 0));
files.add(createQfile('.', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Invalid File Name');
});
test('File Name is ..', () => {
const files = new java.util.ArrayList();
files.add(createQfile('テスト', 0));
files.add(createQfile('..', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Invalid File Name');
});
test('File Names are duplicated', () => {
const files = new java.util.ArrayList();
files.add(createQfile('...', 0));
files.add(createQfile('...', 0));
prepareConfigs(configs, files, '');
expect(execute).toThrow('Two or more files to upload have the same name.');
});
test('Fail to multipart upload', () => {
const files = new java.util.ArrayList();
files.add(createQfile('fail.txt', 8));
prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType}) => {
expect(url).toEqual('https://upload.box.com/api/2.0/files/content?fields=id');
expect(method).toEqual('POST');
expect(contentType).startsWith('multipart/form-data');
return httpClient.createHttpResponse(409, 'application/json', JSON.stringify({}));
});
expect(execute).toThrow('failed to upload\nstatus: 409\nfile: fail.txt');
});
test('Failed to create upload session', () => {
const FILE_SIZE = 52428800 + 4;
const files = new java.util.ArrayList();
files.add(createQfile('large.txt', FILE_SIZE));
prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType}) => {
expect(url).toEqual('https://upload.box.com/api/2.0/files/upload_sessions');
expect(method).toEqual('POST');
return httpClient.createHttpResponse(403, 'application/json', JSON.stringify({}));
});
expect(execute).toThrow('failed to create upload session \nstatus: 403\nfile: large.txt');
});
test('Failed to partial upload', () => {
const FILE_SIZE = 52428800 + 4;
const PART_SIZE = FILE_SIZE / 2;
const files = new java.util.ArrayList();
files.add(createQfile('large.txt', FILE_SIZE));
prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType}) => {
engine.log(url);
switch (url) {
case 'https://upload.box.com/api/2.0/files/upload_sessions': {
expect(method).toEqual('POST');
const responseObj = {
"id": "S0",
"type": "upload_session",
"part_size": PART_SIZE
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S0': {
expect(method).toEqual('PUT');
return httpClient.createHttpResponse(412, 'application/json', '{}');
}
default:
fail('Request Error');
}
});
expect(execute).toThrow('failed to upload\nstatus: 412\nfile: large.txt');
});
test('Failed to commit upload session', () => {
const FILE_SIZE = 52428800 + 4;
const PART_SIZE = FILE_SIZE / 2;
const files = new java.util.ArrayList();
files.add(createQfile('大きい.txt', FILE_SIZE));
prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType}) => {
engine.log(url);
switch (url) {
case 'https://upload.box.com/api/2.0/files/upload_sessions': {
expect(method).toEqual('POST');
const responseObj = {
"id": "S0",
"type": "upload_session",
"part_size": PART_SIZE
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S0': {
expect(method).toEqual('PUT');
const responseObj = {
"part": {
"size": PART_SIZE
}
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S0/commit?fields=id': {
expect(method).toEqual('POST');
return httpClient.createHttpResponse(416, 'application/json', '{}');
}
default:
fail('Request Error');
}
});
expect(execute).toThrow('failed to commit upload session \nstatus: 416\nfile: 大きい.txt');
});
test('File Count > 1 and FileId is TextField', () => {
const files = new java.util.ArrayList();
files.add(createQfile('1.txt', 0));
files.add(createQfile('2.txt', 0));
prepareConfigs(configs, files, '');
// TEXTFIELD に上書き
const idDef = engine.createDataDefinition('ファイルID', 2, 'q_ids', 'STRING_TEXTFIELD');
configs.putObject('fileId', idDef);
expect(execute).toThrow('Multiple files are set though the Data Item to save the output is Single-line String.');
});
test('File Count > 1 and FileUrl is TextField', () => {
const files = new java.util.ArrayList();
files.add(createQfile('1.txt', 0));
files.add(createQfile('2.txt', 0));
prepareConfigs(configs, files, '');
// TEXTFIELD に上書き
const urlDef = engine.createDataDefinition('ファイルURL', 3, 'q_urls', 'STRING_TEXTFIELD');
configs.putObject('fileUrl', urlDef);
expect(execute).toThrow('Multiple files are set though the Data Item to save the output is Single-line String.');
});
test('File Count = 1 and FileId FileUrl is TextField', () => {
const files = new java.util.ArrayList();
files.add(createQfile('1.txt', 10));
prepareConfigs(configs, files, '12345');
// TEXTFIELD に上書き
const idDef = engine.createDataDefinition('ファイルID', 2, 'q_ids', 'STRING_TEXTFIELD');
configs.putObject('fileId', idDef);
const urlDef = engine.createDataDefinition('ファイルURL', 3, 'q_urls', 'STRING_TEXTFIELD');
configs.putObject('fileUrl', urlDef);
httpClient.setRequestHandler(({url, method, contentType, body}) => {
expect(url).toEqual('https://upload.box.com/api/2.0/files/content?fields=id');
expect(method).toEqual('POST');
expect(contentType).startsWith('multipart/form-data');
expect(body.size()).toEqual(2);
const attributes = JSON.parse(body.get('attributes').get(0));
expect(attributes.parent.id).toEqual('12345');
expect(attributes.name).toEqual('1.txt');
const file = body.get('file').get(0);
expect(file.getName()).toEqual('1.txt');
expect(file.getContentType()).startsWith('text/plain');
expect(file.getLength()).toEqual(10);
const responseObj = {
"entries": [
{
"id": 1234,
"etag": 1,
"type": "file"
}
],
"total_count": 1
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
execute();
expect(engine.findData(idDef)).toEqual('1234');
expect(engine.findData(urlDef)).toEqual('https://app.box.com/file/1234');
});
test('Failed to Upload too Large File', () => {
const maxRequests = httpClient.getRequestingLimit() - 2;
const FILE_SIZE = 52428800 + 1;
const PART_SIZE = Math.ceil(FILE_SIZE / maxRequests) - 1; // HTTP request わずかに足りない PART_SIZE
const files = new java.util.ArrayList();
files.add(createQfile('large.txt', FILE_SIZE));
prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType}) => {
expect(url).toEqual('https://upload.box.com/api/2.0/files/upload_sessions');
expect(method).toEqual('POST');
const responseObj = {
"id": `S99999`,
"type": "upload_session",
"part_size": PART_SIZE
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
expect(execute).toThrow('Number of requests is over the limit');
});
test('Failed to Upload Large File and Small File', () => {
const maxRequests = httpClient.getRequestingLimit() - 2;
const FILE_SIZE = 52428800 + 1;
const PART_SIZE = Math.ceil(FILE_SIZE / maxRequests); // HTTP request ぎりぎりの PART_SIZE
const files = new java.util.ArrayList();
files.add(createQfile('large.txt', FILE_SIZE));
files.add(createQfile('smal.txt', 0)); // サイズの小さなファイルがあるため、request 数が足りない
prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType}) => {
expect(url).toEqual('https://upload.box.com/api/2.0/files/upload_sessions');
expect(method).toEqual('POST');
const responseObj = {
"id": `S99999`,
"type": "upload_session",
"part_size": PART_SIZE
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
});
expect(execute).toThrow('Number of requests is over the limit');
});
test('Succeed to Upload Large File', () => {
const maxRequests = httpClient.getRequestingLimit() - 2;
const FILE_SIZE = 52428800 + 1;
const PART_SIZE = Math.ceil(FILE_SIZE / maxRequests); // HTTP request 使い切る PART_SIZE
const files = new java.util.ArrayList();
files.add(createQfile('large.txt', FILE_SIZE));
const {
idDef,
urlDef
} = prepareConfigs(configs, files, '');
httpClient.setRequestHandler(({url, method, contentType, body}) => {
engine.log(url);
switch (url) {
case 'https://upload.box.com/api/2.0/files/upload_sessions': {
expect(method).toEqual('POST');
expect(contentType).toEqual('application/json; charset=UTF-8');
const bodyObj = JSON.parse(body);
expect(bodyObj.file_name).toEqual('large.txt');
expect(bodyObj.file_size).toEqual(FILE_SIZE);
expect(bodyObj.folder_id).toEqual('0');
const responseObj = {
"id": `S99999`,
"type": "upload_session",
"part_size": PART_SIZE
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S99999': {
expect(method).toEqual('PUT');
const responseObj = {
"part": {
"size": PART_SIZE
}
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S99999/commit?fields=id': {
expect(method).toEqual('POST');
const responseObj = {
"entries": [
{
"id": 98765,
"etag": 1,
"type": "file"
}
],
"total_count": 1
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
default:
fail('Request Error');
}
});
execute();
expect(engine.findData(idDef)).toEqual('98765');
expect(engine.findData(urlDef)).toEqual('https://app.box.com/file/98765');
});
test('Succeed to Upload multiple size files', () => {
const FILE_SIZE = 52428800 + 4;
const PART_SIZE = FILE_SIZE / 2;
const files = new java.util.ArrayList();
files.add(createQfile('...', 8));
files.add(createQfile('large.txt', FILE_SIZE));
files.add(createQfile('大きい.txt', FILE_SIZE));
files.add(createQfile('test テスト', 16));
const {
idDef,
urlDef
} = prepareConfigs(configs, files, '12345');
let fileCount = 0;
const fileIds = [10, 20, 30, 40];
let sessionCount = 0;
httpClient.setRequestHandler(({url, method, contentType, body}) => {
engine.log(url);
switch (url) {
case 'https://upload.box.com/api/2.0/files/content?fields=id': {
expect(method).toEqual('POST');
expect(contentType).startsWith('multipart/form-data');
expect(body.size()).toEqual(2);
const attributes = JSON.parse(body.get('attributes').get(0));
expect(attributes.parent.id).toEqual('12345');
const file = body.get('file').get(0);
expect(file.getContentType()).startsWith('text/plain');
const responseObj = {
"entries": [
{
"id": fileIds[fileCount++],
"etag": 1,
"type": "file"
}
],
"total_count": 1
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions': {
expect(method).toEqual('POST');
expect(contentType).toEqual('application/json; charset=UTF-8');
const bodyObj = JSON.parse(body);
expect(bodyObj.file_size).toEqual(FILE_SIZE);
expect(bodyObj.folder_id).toEqual('12345');
const responseObj = {
"id": `S${sessionCount++}`,
"type": "upload_session",
"part_size": PART_SIZE
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S0':
case 'https://upload.box.com/api/2.0/files/upload_sessions/S1': {
expect(method).toEqual('PUT');
const responseObj = {
"part": {
"size": PART_SIZE
}
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
case 'https://upload.box.com/api/2.0/files/upload_sessions/S0/commit?fields=id':
case 'https://upload.box.com/api/2.0/files/upload_sessions/S1/commit?fields=id': {
expect(method).toEqual('POST');
const responseObj = {
"entries": [
{
"id": fileIds[fileCount++],
"etag": 1,
"type": "file"
}
],
"total_count": 1
};
return httpClient.createHttpResponse(200, 'application/json', JSON.stringify(responseObj));
}
default:
fail('Request Error');
}
});
execute();
expect(engine.findData(idDef)).toEqual('10\n20\n30\n40');
expect(engine.findData(urlDef)).toEqual('https://app.box.com/file/10\nhttps://app.box.com/file/20\nhttps://app.box.com/file/30\nhttps://app.box.com/file/40');
});
]]>