

Amazon S3: Download File
This item downloads the specified files on Amazon S3. You can download multiple files at once. When you download multiple files, you should write one Object Key per line.
Basic Configs
- Step Name
- Note
Configs for this Auto Step
- conf_AccessKey
- C1: Access Key *
- conf_SecretKey
- C2: Secret Access Key *
- conf_Region
- C3: Region Code *
- conf_Bucket
- C4: Bucket Name *
- conf_Keys
- C5: Object Keys of the files to download *
- conf_Files
- C6: Data item to add the downloaded files *
Notes
- To learn about how to create your Access Key and Secret Access Key, see the Amazon Web Services Documentation
Capture

See also
Script (click to open)
- An XML file that contains the code below is available to download
- aws-s3-file-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 MAX_OBJECT_KEY_BYTES = 1024;
function main() {
////// == 工程コンフィグ・ワークフローデータの参照 / Config & Data Retrieving ==
const awsKey = configs.getObject("conf_AccessKey").getToken();
const awsSecret = configs.getObject("conf_SecretKey").getToken();
const region = retrieveRegion();
const bucket = retrieveBucket();
const objectKeys = retrieveObjectKeys();
////// == 演算 / Calculating ==
if (objectKeys.length === 0) {
return;
}
const fileDef = configs.getObject("conf_Files");
const files = engine.findData(fileDef) ?? new java.util.ArrayList();
objectKeys.forEach(objectKey => {
const newFile = downloadFile(awsKey, awsSecret, region, bucket, objectKey);
files.add(newFile);
});
engine.setData(fileDef, files);
}
/**
* config からリージョンコードを読み出す
* リージョンコードの形式として不正な場合はエラー
* @return {String}
*/
function retrieveRegion() {
const region = configs.get("conf_Region");
// 今後リージョンが増えることも考えて、中央の最大文字数には余裕をみている
const reg = new RegExp("^[a-z]{2}-[a-z]{4,16}-[1-9]$");
if (!reg.test(region)) {
throw new Error("Region Code is invalid.");
}
return region;
}
/**
* form-type="SELECT" editable="true"
* の設定値を読み出す
* @return {String}
*/
function getConfSelectValue(configName) {
const def = configs.getObject(configName);
if (def === null) {
return configs.get(configName);
}
return engine.findData(def) ?? "";
}
/**
* config からバケット名を読み出す
* バケット名の形式として不正な場合はエラー
* @return {String}
*/
function retrieveBucket() {
const bucket = getConfSelectValue("conf_Bucket");
if (bucket === "") {
throw new Error("Bucket Name is blank.");
}
const reg = new RegExp("^[0-9a-z][0-9a-z-.]{1,61}[0-9a-z]$");
if (!reg.test(bucket) || bucket.includes("..")) {
throw new Error("Bucket Name is invalid.");
}
return bucket;
}
/**
* config からオブジェクトキーを読み出す
* @return {Array<String>}
*/
function retrieveObjectKeys() {
const keyStr = getConfSelectValue("conf_Keys");
const keys = keyStr.split("\n").filter(key => key.length !== 0); // 空行は読み飛ばす。
keys.forEach(key => {
if (encodeURIComponent(key).replace(/%../g, "x").length > MAX_OBJECT_KEY_BYTES) {
throw new Error(`The object key "${key}" is too long. Object key must be less than ${MAX_OBJECT_KEY_BYTES} bytes.`);
}
if(key.endsWith('/')) {
throw new Error(`The object key "${key}" is invalid. Object key must not end with a slash.`);
}
});
if (keys.length > httpClient.getRequestingLimit()) {
throw new Error("The number of object keys exceeds the limit.");
}
return keys;
}
/**
* 保存時のファイル名の最大長
*/
const FILE_NAME_MAX_LENGTH = 200;
/**
* ファイルダウンロード
* @param key アクセスキー
* @param secret シークレットアクセスキー
* @param region リージョン
* @param bucket バケット
* @param objectKey オブジェクトキー
*/
function downloadFile(key, secret, region, bucket, objectKey) {
const encodedObjectKey = encodeURIComponent(objectKey);
const url = `https://${bucket}.s3.${region}.amazonaws.com/${encodedObjectKey}`;
const response = httpClient.begin()
.awsSignV4(key, secret, region, "s3")
.header("x-amz-checksum-mode", "ENABLED")
.get(url);
const status = response.getStatusCode();
if (status !== 200) {
engine.log(response.getResponseAsString());
throw new Error(`Failed to download "${objectKey}" from S3. status: ${status}`);
}
const data = response.getResponse();
// SHA-256 か SHA-1 のチェックサムがある場合、検証
validateChecksum(objectKey, response, "x-amz-checksum-sha256", () => digest.sha256(data));
validateChecksum(objectKey, response, "x-amz-checksum-sha1", () => digest.sha1(data));
let fileName = objectKey.split("/").pop();
if(fileName.length > FILE_NAME_MAX_LENGTH) {
fileName = fileName.substring(0, FILE_NAME_MAX_LENGTH-3) + "...";
}
return new com.questetra.bpms.core.event.scripttask.NewQfile(
fileName,
response.getContentType(),
data
);
}
/**
* チェックサムの検証
* @param objectKey ダウンロードしたファイルのオブジェクトキー
* @param response レスポンス
* @param headerName チェックサムヘッダー名
* @param calculate チェックサムを計算する関数
*/
function validateChecksum(objectKey, response, headerName, calculate) {
let checksumHeaders = response.getHeaderValues(headerName);
if (checksumHeaders.isEmpty()) {
return;
}
const checksum = checksumHeaders.get(0);
const calculated = base64.encodeToString(calculate());
if (checksum !== calculated) {
throw new Error(`The checksum of the downloaded file "${objectKey}" does not match. s3: ${checksum}, file: ${calculated}`);
}
engine.log(`Checksum of "${objectKey}" is OK. ${checksum}`);
}



