(
file: { type: string; data: string; name: string; mime?: string },
executionContext: { workspaceId: string; workflowId: string; executionId: string },
requestId: string,
userId?: string
)
| 13 | * Process a single file for workflow execution - handles base64 ('file' type) and URL downloads ('url' type) |
| 14 | */ |
| 15 | export async function processExecutionFile( |
| 16 | file: { type: string; data: string; name: string; mime?: string }, |
| 17 | executionContext: { workspaceId: string; workflowId: string; executionId: string }, |
| 18 | requestId: string, |
| 19 | userId?: string |
| 20 | ): Promise<UserFile | null> { |
| 21 | if (file.type === 'file' && file.data && file.name) { |
| 22 | const dataUrlPrefix = 'data:' |
| 23 | const base64Prefix = ';base64,' |
| 24 | |
| 25 | if (!file.data.startsWith(dataUrlPrefix)) { |
| 26 | logger.warn(`[${requestId}] Invalid data format for file: ${file.name}`) |
| 27 | return null |
| 28 | } |
| 29 | |
| 30 | const base64Index = file.data.indexOf(base64Prefix) |
| 31 | if (base64Index === -1) { |
| 32 | logger.warn(`[${requestId}] Invalid data format (no base64 marker) for file: ${file.name}`) |
| 33 | return null |
| 34 | } |
| 35 | |
| 36 | const mimeType = file.data.substring(dataUrlPrefix.length, base64Index) |
| 37 | const base64Data = file.data.substring(base64Index + base64Prefix.length) |
| 38 | const buffer = Buffer.from(base64Data, 'base64') |
| 39 | |
| 40 | if (buffer.length > MAX_FILE_SIZE) { |
| 41 | const fileSizeMB = (buffer.length / (1024 * 1024)).toFixed(2) |
| 42 | throw new Error( |
| 43 | `File "${file.name}" exceeds the maximum size limit of 20MB (actual size: ${fileSizeMB}MB)` |
| 44 | ) |
| 45 | } |
| 46 | |
| 47 | const userFile = await uploadExecutionFile( |
| 48 | executionContext, |
| 49 | buffer, |
| 50 | file.name, |
| 51 | mimeType || file.mime || 'application/octet-stream', |
| 52 | userId |
| 53 | ) |
| 54 | |
| 55 | return userFile |
| 56 | } |
| 57 | |
| 58 | if (file.type === 'url' && file.data) { |
| 59 | const { downloadFileFromUrl } = await import('@/lib/uploads/utils/file-utils.server') |
| 60 | const buffer = await downloadFileFromUrl(file.data, { userId }) |
| 61 | |
| 62 | if (buffer.length > MAX_FILE_SIZE) { |
| 63 | const fileSizeMB = (buffer.length / (1024 * 1024)).toFixed(2) |
| 64 | throw new Error( |
| 65 | `File "${file.name}" exceeds the maximum size limit of 20MB (actual size: ${fileSizeMB}MB)` |
| 66 | ) |
| 67 | } |
| 68 | |
| 69 | const userFile = await uploadExecutionFile( |
| 70 | executionContext, |
| 71 | buffer, |
| 72 | file.name, |
no test coverage detected