actions/download-file/download-file.mjs
import fs from "fs"; import stream from "stream"; import { promisify } from "util"; import { GOOGLE_DRIVE_MIME_TYPE_PREFIX } from "../../common/constants.mjs"; import { toSingleLineString } from "../../common/utils.mjs"; import googleDrive from "../../google_drive.app.mjs"; import googleWorkspaceExportFormats from "../common/google-workspace-export-formats.mjs"; export default { key: "google_drive-download-file", name: "Download File", description: "Download a file. [See the documentation](https://developers.google.com/drive/api/v3/manage-downloads) for more information", version: "0.1.17", annotations: { destructiveHint: false, openWorldHint: true, readOnlyHint: false, }, type: "action", props: { googleDrive, drive: { propDefinition: [ googleDrive, "watchedDrive", ], optional: true, }, fileId: { propDefinition: [ googleDrive, "fileId", (c) => ({ drive: c.drive, }), ], description: "The file to download", }, filePath: { type: "string", label: "Destination File Path", description: toSingleLineString(` The destination file name or path [in the \`/tmp\` directory](https://pipedream.com/docs/workflows/steps/code/nodejs/working-with-files/#the-tmp-directory) (e.g., \`/tmp/myFile.csv\`) `), optional: true, }, mimeType: { type: "string", label: "Conversion Format", description: toSingleLineString(` The format to which to convert the downloaded file if it is a [Google Workspace document](https://developers.google.com/drive/api/v3/ref-export-formats) `), optional: true, async options() { const fileId = this.fileId; if (!fileId) { return googleWorkspaceExportFormats; } let file, exportFormats; try { ([ file, exportFormats, ] = await Promise.all([ this.googleDrive.getFile(fileId, { fields: "mimeType", }), this.googleDrive.getExportFormats(), ])); } catch (err) { return googleWorkspaceExportFormats; } const mimeTypes = exportFormats[file.mimeType]; if (!mimeTypes) { return []; } return exportFormats[file.mimeType].map((f) => googleWorkspaceExportFormats.find( (format) => format.value === f, ) ?? { value: f, label: f, }); }, }, syncDir: { type: "dir", accessMode: "write", sync: true, }, getBufferResponse: { type: "boolean", label: "Get Buffer Response", description: "Whether to return the file content as a buffer instead of writing to a file path", optional: true, }, }, async run({ $ }) { if (!this.getBufferResponse && !this.filePath) { throw new Error("File Path is required when not using Get Buffer Response"); } const fileMetadata = await this.googleDrive.getFile(this.fileId, { fields: "name,mimeType", }); const mimeType = fileMetadata.mimeType; const isWorkspaceDocument = mimeType.includes(GOOGLE_DRIVE_MIME_TYPE_PREFIX); if (isWorkspaceDocument && !this.mimeType) { throw new Error("Conversion Format is required when File is a Google Workspace Document"); } const file = isWorkspaceDocument ? await this.googleDrive.downloadWorkspaceFile(this.fileId, { mimeType: this.mimeType, }) : await this.googleDrive.getFile(this.fileId, { alt: "media", }); if (this.getBufferResponse) { $.export("$summary", `Successfully retrieved raw content for file "${fileMetadata.name}"`); const chunks = []; for await (const chunk of file) { chunks.push(chunk); } const buffer = Buffer.concat(chunks); return { fileMetadata, content: buffer, }; } const pipeline = promisify(stream.pipeline); const filePath = this.filePath.includes("tmp/") ? this.filePath : `/tmp/${this.filePath}`; await pipeline(file, fs.createWriteStream(filePath)); $.export("$summary", `Successfully downloaded the file, "${fileMetadata.name}"`); return { fileMetadata, filePath, }; }, };