MCPcopy Index your code
hub / github.com/simstudioai/sim / uploadViaMultipart

Function uploadViaMultipart

apps/sim/lib/uploads/client/direct-upload.ts:331–527  ·  view source on GitHub ↗
(
  opts: MultipartUploadOptions
)

Source from the content-addressed store, hash-verified

329}
330
331const uploadViaMultipart = async (
332 opts: MultipartUploadOptions
333): Promise<{ key: string; path: string }> => {
334 const { file, workspaceId, context, workflowId, executionId, signal, onProgress } = opts
335
336 // boundary-raw-fetch: multipart upload control plane uses action query strings; client lifecycle (initiate/get-part-urls/complete/abort) is sequenced manually and not modeled by a single contract
337 const initiateResponse = await fetch('/api/files/multipart?action=initiate', {
338 method: 'POST',
339 headers: { 'Content-Type': 'application/json' },
340 body: JSON.stringify({
341 fileName: file.name,
342 contentType: getFileContentType(file),
343 fileSize: file.size,
344 workspaceId,
345 context,
346 ...(workflowId ? { workflowId } : {}),
347 ...(executionId ? { executionId } : {}),
348 }),
349 signal,
350 })
351
352 if (!initiateResponse.ok) {
353 let errorBody: { error?: string } | null = null
354 try {
355 errorBody = (await initiateResponse.clone().json()) as { error?: string }
356 } catch {}
357 if (
358 initiateResponse.status === 400 &&
359 typeof errorBody?.error === 'string' &&
360 errorBody.error.toLowerCase().includes('cloud storage')
361 ) {
362 throw new DirectUploadError(
363 'Server signaled fallback to API upload',
364 'FALLBACK_REQUIRED',
365 errorBody
366 )
367 }
368 throw new DirectUploadError(
369 `Failed to initiate multipart upload: ${initiateResponse.statusText}`,
370 'MULTIPART_ERROR',
371 undefined,
372 initiateResponse.status
373 )
374 }
375
376 const { key, uploadToken } = (await initiateResponse.json()) as {
377 uploadId: string
378 key: string
379 uploadToken: string
380 }
381
382 const numParts = Math.ceil(file.size / CHUNK_SIZE)
383 const partNumbers = Array.from({ length: numParts }, (_, i) => i + 1)
384
385 const abortMultipart = async () => {
386 try {
387 // boundary-raw-fetch: fire-and-forget abort during multipart cleanup; intentionally avoids contract response parsing so cleanup cannot mask the original error
388 await fetch('/api/files/multipart?action=abort', {

Callers 1

runUploadStrategyFunction · 0.85

Calls 4

getFileContentTypeFunction · 0.90
abortMultipartFunction · 0.85
runWithConcurrencyFunction · 0.70
pushMethod · 0.45

Tested by

no test coverage detected