

Google ドライブ: ファイルコピー
この工程は、Google ドライブ上の指定ファイルをコピーします。保存先のフォルダや新しいファイル名を任意で設定でき、作成さ れたファイルの ID や表示用 URL を保存できます。
Basic Configs
- 工程名
- メモ
Configs for this Auto Step
- conf_Auth
- C1: サービスアカウント設定 *
- conf_SourceFileId
- C2: コピー元ファイルの ID *
- conf_DestinationFolderId
- C3: 保存先フォルダの ID(空欄の場合、コピー元と同じ場所に作成されます)
- conf_NewFileName
- C4: 新しいファイル名(空欄の場合、自動的に設定されます)#{EL}
- conf_NewFileIdItem
- C5: 作成されたファイル ID を保存するデータ項目
- conf_NewFileUrlItem
- C6: 作成されたファイルの表示用 URL を保存するデータ項目
Notes
- ダウンロードするファイルは、事前に[C1: サービスアカウント設定]のサービスアカウントと共有しておく必要があります
- [C1: サービスアカウント設定]を設定するには:
- Google Cloud コンソールでサービスアカウントを準備します
- サービスアカウントキーを作成またはアップロードします
- Google Cloud コンソール上でサービスアカウントキーを作成すると、必要な情報を含む JSON ファイルをダウンロードできます
- サービスアカウントキーを作成またはアップロードします
- Questetra BPM Suite で OAuth2 JWT ベアラーフローの設定を作成し、C1 に設定します
- スコープ
https://www.googleapis.com/auth/driveが必要です - 以降の項目は、下表のとおり設定してください
- スコープ
- Google Cloud コンソールでサービスアカウントを準備します
| Questetra BPM Suite の設定項目 | 対応する Google Cloud サービスアカウントキーの情報 | JSON ファイルの項目名 | 設定必須かどうか |
|---|---|---|---|
| クライアント ID | OAuth2 クライアント ID | client_id | 任意 |
| 秘密鍵 ID | キー ID | private_key_id | 必須 |
| 秘密鍵 | 秘密鍵 | private_key | 必須 |
| カスタム秘密情報 1 | メールアドレス | client_email | 必須 |

Errors
"code": 403, "message": "Google Drive API has not been used in project 123456789012 before or it is disabled."- 『Google Drive API』を有効化する必要があります。
"code": 404, "message": "File not found:"- ファイルが存在しない可能性があります。
- 『Google サービスアカウント』がファイルへの閲覧権限を持っていない可能性があります。
Capture

See Also
Script (click to open)
- 次のスクリプトが記述されている XML ファイルをダウンロードできます
- google-drive-file-copy.xml (C) Questetra, Inc. (MIT License)
- Professional のワークフロー基盤では、ファイル内容を改変しオリジナルのアドオン自動工程として活用できます
const COPY_FIELDS = 'id,name,parents,webViewLink';
function main() {
const auth = configs.getObject('conf_Auth');
const sourceFileId = getSourceFileId();
const destinationFolderId = getDestinationFolderId();
const newFileName = getNewFileName();
const newFileIdDataDef = configs.getObject('conf_NewFileIdItem');
const newFileUrlDataDef = configs.getObject('conf_NewFileUrlItem');
const copiedFile = copyFile(auth, sourceFileId, destinationFolderId, newFileName);
engine.log(`Succeeded to copy. Source ID: ${sourceFileId}, New ID: ${copiedFile.id}`);
if (newFileIdDataDef !== null) {
engine.setData(newFileIdDataDef, copiedFile.id);
}
if (newFileUrlDataDef !== null) {
const webViewUrl = copiedFile.webViewLink ?? `https://drive.google.com/file/d/${copiedFile.id}/view`;
engine.setData(newFileUrlDataDef, webViewUrl);
}
}
/**
* コピー元のファイル ID を取得する
* @return {String} コピー元ファイル ID
*/
function getSourceFileId() {
let fileId = configs.get('conf_SourceFileId');
const fileIdDef = configs.getObject('conf_SourceFileId');
if (fileIdDef !== null) {
fileId = engine.findData(fileIdDef);
}
if (fileId === null) {
throw "Source File ID isn't set.";
}
const trimmed = fileId.trim();
if (trimmed === '') {
throw "Source File ID isn't set.";
}
return trimmed;
}
/**
* 保存先フォルダ ID を取得する(未指定の場合は空文字を返す)
* @return {String} 保存先フォルダ ID または空文字
*/
function getDestinationFolderId() {
let folderId = configs.get('conf_DestinationFolderId');
const folderIdDef = configs.getObject('conf_DestinationFolderId');
if (folderIdDef !== null) {
folderId = engine.findData(folderIdDef);
}
if (folderId === null) {
return '';
}
return folderId.trim();
}
/**
* 新しいファイル名を取得する(未指定の場合は空文字を返す)
* @return {String} 新しいファイル名または空文字
*/
function getNewFileName() {
const newName = configs.get('conf_NewFileName');
if (newName === null) {
return '';
}
return newName.trim();
}
/**
* ファイルをコピーする
* @param {HttpAuthSettingWrapper} auth 認証設定
* @param {String} sourceFileId コピー元のファイル ID
* @param {String} destinationFolderId 保存先フォルダ ID
* @param {String} newFileName 新しいファイル名
* @return {Object} コピー後のファイル情報
*/
function copyFile(auth, sourceFileId, destinationFolderId, newFileName) {
const url = `https://www.googleapis.com/drive/v3/files/${encodeURIComponent(sourceFileId)}/copy`;
const body = {};
if (destinationFolderId !== '') {
body.parents = [destinationFolderId];
}
if (newFileName !== '') {
body.name = newFileName;
}
const response = httpClient.begin()
.oauth2JwtBearer(auth, () => getAccessToken(auth))
.queryParam('fields', COPY_FIELDS)
.queryParam('supportsAllDrives', 'true')
.body(JSON.stringify(body), 'application/json; charset=UTF-8')
.post(url);
const status = response.getStatusCode();
const responseBody = response.getResponseAsString();
if (status >= 300) {
engine.log(responseBody);
throw `Failed to copy. Source ID: ${sourceFileId}, status: ${status}`;
}
let json;
try {
json = JSON.parse(responseBody);
} catch (error) {
throw `Failed to parse response. Source ID: ${sourceFileId}`;
}
if (json.id === undefined) {
throw `Failed to retrieve new file information. Source ID: ${sourceFileId}`;
}
return json;
}
const URL_TOKEN_REQUEST = 'https://oauth2.googleapis.com/token';
const SCOPE = 'https://www.googleapis.com/auth/drive';
/**
* @param {HttpAuthSettingWrapper} auth HTTP 認証設定
* @returns {{access_token: string}} アクセストークンを含むオブジェクト
*/
function 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,
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(responseText);
if (result.access_token === undefined) {
engine.log(responseText);
throw new Error('Failed to get Access token. access token not found.');
}
return result;
}



