diff --git a/apps/sim/app/api/tools/google_drive/download/route.ts b/apps/sim/app/api/tools/google_drive/download/route.ts index e4131423f91..e2733e73abc 100644 --- a/apps/sim/app/api/tools/google_drive/download/route.ts +++ b/apps/sim/app/api/tools/google_drive/download/route.ts @@ -13,6 +13,7 @@ import { ALL_REVISION_FIELDS, DEFAULT_EXPORT_FORMATS, GOOGLE_WORKSPACE_MIME_TYPES, + VALID_EXPORT_FORMATS, } from '@/tools/google_drive/utils' export const dynamic = 'force-dynamic' @@ -65,10 +66,12 @@ export async function POST(request: NextRequest) { const { accessToken, fileId, - mimeType: exportMimeType, + mimeType: rawExportMimeType, fileName, includeRevisions, } = validatedData + const exportMimeType = + rawExportMimeType && rawExportMimeType !== 'auto' ? rawExportMimeType : null const authHeader = `Bearer ${accessToken}` logger.info(`[${requestId}] Getting file metadata from Google Drive`, { fileId }) @@ -112,6 +115,24 @@ export async function POST(request: NextRequest) { if (GOOGLE_WORKSPACE_MIME_TYPES.includes(fileMimeType)) { const exportFormat = exportMimeType || DEFAULT_EXPORT_FORMATS[fileMimeType] || 'text/plain' + + const validFormats = VALID_EXPORT_FORMATS[fileMimeType] + if (validFormats && !validFormats.includes(exportFormat)) { + logger.warn(`[${requestId}] Unsupported export format requested`, { + fileId, + fileMimeType, + requestedFormat: exportFormat, + validFormats, + }) + return NextResponse.json( + { + success: false, + error: `Export format "${exportFormat}" is not supported for this file type. Supported formats: ${validFormats.join(', ')}`, + }, + { status: 400 } + ) + } + finalMimeType = exportFormat logger.info(`[${requestId}] Exporting Google Workspace file`, { diff --git a/apps/sim/blocks/blocks/google_drive.ts b/apps/sim/blocks/blocks/google_drive.ts index 79ab814e04e..6feff2d80f9 100644 --- a/apps/sim/blocks/blocks/google_drive.ts +++ b/apps/sim/blocks/blocks/google_drive.ts @@ -316,6 +316,7 @@ Return ONLY the query string - no explanations, no quotes around the whole thing title: 'Export Format', type: 'dropdown', options: [ + { label: 'Auto (best format for file type)', id: 'auto' }, { label: 'Plain Text (text/plain)', id: 'text/plain' }, { label: 'HTML (text/html)', id: 'text/html' }, { label: 'PDF (application/pdf)', id: 'application/pdf' }, @@ -333,7 +334,8 @@ Return ONLY the query string - no explanations, no quotes around the whole thing }, { label: 'CSV (text/csv)', id: 'text/csv' }, ], - placeholder: 'Optional: Choose export format for Google Docs/Sheets/Slides', + value: () => 'auto', + placeholder: 'Export format for Google Docs/Sheets/Slides', condition: { field: 'operation', value: 'download' }, }, { @@ -867,7 +869,7 @@ Return ONLY the message text - no subject line, no greetings/signatures, no extr destinationFolderId: effectiveDestinationFolderId, file: normalizedFile, pageSize: rest.pageSize ? Number.parseInt(rest.pageSize as string, 10) : undefined, - mimeType: mimeType, + mimeType: mimeType === 'auto' ? undefined : mimeType, type: shareType, // Map shareType to type for share tool starred: starredValue, sendNotification: sendNotificationValue, diff --git a/apps/sim/tools/google_drive/utils.ts b/apps/sim/tools/google_drive/utils.ts index e58b27eb989..fd046cf1b83 100644 --- a/apps/sim/tools/google_drive/utils.ts +++ b/apps/sim/tools/google_drive/utils.ts @@ -111,8 +111,50 @@ export const DEFAULT_EXPORT_FORMATS: Record = { 'application/vnd.google-apps.spreadsheet': 'text/csv', 'application/vnd.google-apps.presentation': 'text/plain', 'application/vnd.google-apps.drawing': 'image/png', - 'application/vnd.google-apps.form': 'application/pdf', - 'application/vnd.google-apps.script': 'application/json', + 'application/vnd.google-apps.form': 'application/zip', + 'application/vnd.google-apps.script': 'application/vnd.google-apps.script+json', +} + +/** + * Valid export formats per Google Workspace file type. + * See: https://developers.google.com/drive/api/guides/ref-export-formats + */ +export const VALID_EXPORT_FORMATS: Record = { + 'application/vnd.google-apps.document': [ + 'text/plain', + 'text/html', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.oasis.opendocument.text', + 'application/rtf', + 'application/epub+zip', + 'text/markdown', + ], + 'application/vnd.google-apps.spreadsheet': [ + 'text/csv', + 'text/tab-separated-values', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.oasis.opendocument.spreadsheet', + 'application/zip', + ], + 'application/vnd.google-apps.presentation': [ + 'text/plain', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.oasis.opendocument.presentation', + 'image/jpeg', + 'image/png', + 'image/svg+xml', + ], + 'application/vnd.google-apps.drawing': [ + 'application/pdf', + 'image/jpeg', + 'image/png', + 'image/svg+xml', + ], + 'application/vnd.google-apps.form': ['application/zip'], + 'application/vnd.google-apps.script': ['application/vnd.google-apps.script+json'], } export const SOURCE_MIME_TYPES: Record = {