
Google Drive: Download File
This item downloads the specified files on Google Drive. You can download multiple files at once. When you download multiple files, you should write one File ID per line.
Basic Configs
- Step Name
- Note
Configs for this Auto Step
- conf_Auth
- C1: Service Account Setting *
- conf_FileIds
- C2: File IDs to download (Write one per line) *
- conf_FileData
- C3: Data item to add the downloaded file *
Notes
- It is required that the files to download be shared in advance with the service account set in [C1: Service Account Setting]
- To set up [C1: Service Account Setting] :
- Prepare a service account on Google Cloud Console
- Create or upload a service account key
- If you create a service account key on Google Cloud Console, you can download a JSON file including necessary information
- Create or upload a service account key
- Create an OAuth2 JWT Bearer setting on Questetra BPM Suite and set it to C1
- Scope
https://www.googleapis.com/auth/drive.readonlyis required - Set up other items as shown in the table below :
- Scope
- Prepare a service account on Google Cloud Console
| Settings on Questetra BPM Suite | Corresponding Information of Google Cloud Service Account Key | Property Name in JSON File | Required or Not |
|---|---|---|---|
| Client ID | OAuth2 Client ID | client_id | Not Required |
| Private Key ID | Key ID | private_key_id | Required |
| Private Key | Private Key | private_key | Required |
| Custom Secret Information 1 | Email Address | client_email | Required |

Errors
"code": 403, "message": "Google Drive API has not been used in project 123456789012 before or it is disabled.".- ‘Google Drive API’ needs to be enabled
"code": 404, "message": "File not found:"- The file may not exist
- ‘Google Service Account’ may not have permission to read the file
Capture

See Also
Script (click to open)
- An XML file that contains the code below is available to download
- google-drive-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 REQUEST_NUM_PER_FILE = 4; // ファイル 1 つにつき 4 回リクエストを行う
function main() {
////// == 工程コンフィグ・ワークフローデータの参照 / Config & Data Retrieving ==
const auth = configs.getObject('conf_Auth');
const fileIds = retrieveFileIds();
const fileDef = configs.getObject('conf_FileData');
let files = engine.findData( fileDef );
if (files === null) {
files = new java.util.ArrayList();
}
////// == 演算 / Calculating ==
if (fileIds.length * REQUEST_NUM_PER_FILE > httpClient.getRequestingLimit()) {
throw new Error('Number of File IDs exceeds the limit.');
}
fileIds.forEach(fileId => {
const {name, contentType} = getFileMetadata(auth, fileId);
const content = getFile(auth, fileId);
const qfile = new com.questetra.bpms.core.event.scripttask.NewQfile(
name, contentType, content
);
files.add(qfile);
});
////// == ワークフローデータへの代入 / Data Updating ==
engine.setData(fileDef, files);
}
/**
* config からファイル ID を読み出す
* ファイル ID が設定されていない場合はエラー
* @returns {Array<String>} ファイル ID の配列
*/
const retrieveFileIds = () => {
let fileIdsStr = configs.get('conf_FileIds');
const fileIdsDef = configs.getObject('conf_FileIds');
if (fileIdsDef !== null) {
fileIdsStr = engine.findData(fileIdsDef);
}
if (fileIdsStr === null) {
throw new Error('No File IDs.');
}
const fileIds = fileIdsStr.split('\n').filter(key => key.length !== 0);
if (fileIds.length === 0) {
throw new Error('No File IDs.');
}
return fileIds;
};
const URL_TOKEN_REQUEST = 'https://oauth2.googleapis.com/token';
const SCOPE = 'https://www.googleapis.com/auth/drive.readonly';
/**
* @param auth HTTP 認証設定
* @returns {any} アクセストークンを含むオブジェクト
*/
const getAccessToken = (auth) => {
const privateKeyId = auth.getPrivateKeyId();
const privateKey = auth.getPrivateKey();
const serviceAccount = auth.getCustomSecret1();
const scope = auth.getScope();
if (!scope.split(' ').includes(SCOPE)) {
throw new Error(`Scope ${SCOPE} must be included in the scope.`);
}
if (privateKeyId === '') {
throw new Error('Private Key ID is required.');
}
if (privateKey === '') {
throw new Error('Private Key is required.');
}
if (serviceAccount === '') {
throw new Error('Service Account must be set to Custom Secret 1.');
}
const header = {
"alg": "RS256",
"typ": "at+jwt",
"kid": privateKeyId
};
const now = Math.floor(Date.now() / 1000);
const payload = {
"iss": serviceAccount,
"aud": URL_TOKEN_REQUEST,
"sub": '',
"iat": now,
"exp": now + 3600,
/**
* https://developers.google.com/identity/protocols/oauth2/service-account#jwt-auth
* "without OAuth" の話だが、OAuth でも 1 hour になるようだ。
* 1 hour より長ければエラー。短ければ、1 hour のトークンが返ってくる。
*/
scope
};
const keyB = rsa.readKeyFromPkcs8(privateKey);
const assertion = jwt.build(header, payload, keyB);
const response = httpClient.begin()
.formParam("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer")
.formParam('assertion', assertion)
.post(URL_TOKEN_REQUEST);
const responseText = response.getResponseAsString();
if (response.getStatusCode() !== 200) {
engine.log(responseText);
throw new Error(`Failed to get Access token. status: ${response.getStatusCode()}`);
}
const result = JSON.parse(response.getResponseAsString());
if (result.access_token === undefined) {
engine.log(responseText);
throw new Error(`Failed to get Access token. access token not found.`);
}
return result;
};
/**
* ファイルメタデータ取得
* @param auth HTTP 認証設定
* @param fileId ファイルID
*/
const getFileMetadata = (auth, fileId) => {
const URL = `https://www.googleapis.com/drive/v3/files/${encodeURIComponent(fileId)}`;
const response = httpClient.begin()
.oauth2JwtBearer(auth, () => getAccessToken(auth))
.queryParam("supportsAllDrives", "true")
.get(URL);
const status = response.getStatusCode();
const respTxt = response.getResponseAsString();
if (status !== 200) {
engine.log(respTxt);
throw new Error(`Failed to get metadata of file. status: ${status}`);
}
const respJson = JSON.parse(respTxt);
return {
name: respJson.name,
contentType: respJson.mimeType
};
};
/**
* ファイル取得
* @param auth HTTP 認証設定
* @param fileId ファイルID
*/
const getFile = (auth, fileId) => {
const URL = `https://www.googleapis.com/drive/v3/files/${encodeURIComponent(fileId)}`;
const response = httpClient.begin()
.oauth2JwtBearer(auth, () => getAccessToken(auth))
.queryParam("supportsAllDrives", "true")
.queryParam("alt", "media")
.get(URL);
const status = response.getStatusCode();
const respTxt = response.getResponseAsString();
if (status !== 200) {
engine.log(respTxt);
throw new Error(`Failed to download file. status: ${status}`);
}
return response.getResponse();
};