Home/Blog/Multipart file uploads explained: Scaling large file transfers with Uploadcare

Multipart file uploads explained: Scaling large file transfers with Uploadcare

What are multipart file uploads?

Multipart upload isย aย file transfer technique that splits large files into smaller chunks, uploads each chunk toย the server independently, and reassembles them into the original file once all pieces arrive.

Think ofย itย like moving furniture into your apartment. Instead ofย trying toย fit anย entire couch through your door in oneย go (which wonโ€™t fit and will beย difficult toย force through), you disassemble itย into smaller pieces, move each piece separately, and reassemble itย inside your apartment. Each piece isย easier toย handle, and ifย one piece gets stuck, you donโ€™t have toย start over with the entire couch.

Why does itย matter for large file transfers? Because large file transfers (e.g. 500ย MB orย 2ย GB) can encounter setbacks and unforeseen issues, such asย unstable internet connections, server limits, timeouts, orย even user behavior that can cancel the upload.

Difference between singleย vs. multipart uploads

Aย single upload method sends anย entire file toย the server inย aย single request. For example, the code below uploads aย file using the single upload method:

// Traditional single upload
const formData = new FormData();
formData.append('file', largeFile);

await fetch('/upload', {
  method: 'POST',
  body: formData
});

While this works fine for small files, itย becomes problematic when dealing with very large uploads.

  • Connection failures: Ifย the userโ€™s connection drops, the entire upload fails and must beย restarted from scratch.
  • Server timeouts: Every server has request time limits. Large file uploads often exceed these limits, causing the connection toย beย terminated.
  • Memory constraints: Uploading large files using this method can spike memory usage on both the client device and the server. Ifย the device doesnโ€™t have enough memory, itย can lead toย performance issues orย crashes.

Multipart uploads, onย the other hand, split aย single file into multiple parts and upload them in parallel. This ensures that large files are uploaded effectively without overwhelming the server, maintains faster speeds, and improves upload reliability.

Why large file transfers fail without multipart uploads

Large file uploads face several challenges that make using traditional single-request upload methods unreliable.

Unstable internet connections

Network connections arenโ€™t always stable. Aย single drop inย Wi-Fi signal, aย mobile network switching between cell towers, orย any network interruption means starting over when uploading aย large file using the single upload method. Inย multipart uploads, aย dropped connection would affect only the current data chunk. The upload resumes from where itย left off, not from the beginning.

Slower upload speed, bandwidth, and latency

The larger aย fileย is, the more bandwidth and time itย takes toย upload.

Upload speed issues often arise when transferring data toย your server inย aย single upload. This isย because, regardless ofย where your end user isย located, all files are sent toย the same destination via the same route.

Soย when users attempt toย upload multiple large files atย the same time, itย can overwhelm your servers, leading toย decreased performance and increased latency.

This issue isย especially pronounced ifย your server isย not properly configured toย handle large file uploads.

Timeout issues

Most web servers and proxies impose timeout limits onย HTTP requests. When uploading aย large file that takes more time than allotted for aย request, aย timeout occurs, and the connection isย interrupted.

For example, ifย youโ€™re uploading aย 1GB file over aย 4ย Mbps connection, itย will take approximately 33ย minutes toย complete. Most servers will kill the connection long before that time expires.

Some common timeout limits for servers look like this:

  • Nginx default: 60ย seconds
  • Apache default: 300 seconds
  • AWS Application Load Balancer: 60ย seconds
  • Cloudflare: 100 seconds for free plans

File size limitations

Many platforms impose hard limits onย upload sizes. For example:

  • Aย PHP server for uploading files, upload_max_filesize, isย often 2-8ย MB byย default.
  • Anย Nginx server client_max_body_size, byย default, isย 1ย MB.
  • AWS API Gateway has aย maximum payload ofย 10ย MB.
  • Most CDNs and proxies usually have limits between 100ย MB and 5ย GB.

Using the multipart upload method can bypass these limitations byย staying under the threshold for each chunk while allowing unlimited total file sizes.

How multipart uploads work (step-by-step)

Every multipart upload process follows aย pattern: split aย large file into smaller chunks, upload them toย the server, and reassemble the file once the upload isย complete.

Uploadcareโ€™s multipart upload, for example, accepts aย large file and uses file information (such asย file size, and size ofย each chunk) toย generate aย set ofย presigned URLs for uploading each chunk. When the upload completes, itย assembles the chunks into one complete file.

Letโ€™s walk through the process.

Stepย 1: Initialize the upload and generate presigned URLs

First, the Upload API receives the large file along with details needed toย processย it:

  • The file itself
  • The file size
  • The chunk size, which tells the server how large each chunk shouldย be. The 5ย MB default isย used unless you specify otherwise.

When received, the Upload API divides the file size byย the chunk size toย generate presigned URLs for each chunk. Aย 50ย MB file with aย 5ย MB chunk size will generate 10ย presigned URLs, one for each chunk.

Uploadcareโ€™s multipart upload feature uses AWS S3ย Transfer Acceleration toย speed uploads.

Aย typical generated presigned URL looks like this:

https://uploadcare.s3-accelerate.amazonaws.com/
5eef12e3-e72a-4bf5-b68a-89953e81c7db/500MBCZIPtestfileorg.zip?
uploadId=0QMRh4VdwZGKMOVZuVsAONK3TmfD0gBwRbgWbmThZZghD9JFe2GY2GRASe5SbbZy2mAo2sXjgpg7l3BdmIvzKV9EOgTQ0B.TYgKyAOd1ZlxtDCbFg2V032nqoMWv7FyR
&partNumber=47
&X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=AKIA5C7IQCBHHHZXJRAU%2F20251006%2Fus-east-1%2Fs3%2Faws4_request
&X-Amz-Date=20251006T075132Z
&X-Amz-Expires=86400
&X-Amz-SignedHeaders=host
&X-Amz-Signature=194f63da4c429d2d5af2d7bade6a468ce521987d533af3b2f6ebc2b3f8a21364

Where:

  • https://uploadcare.s3-accelerate.amazonaws.com: Domain with Transfer Acceleration enabled
  • /5eef12e3-e72a-4bf5-b68a-89953e81c7db/500MBCZIPtestfileorg.zip: File UUID and original filename
  • uploadId: Multipart sessionย ID that tracks this specific upload
  • partNumber=47: This isย chunk #47 ofย the file
  • X-Amz-Algorithm=AWS4-HMAC-SHA256: Signature algorithm for signing the URL
  • X-Amz-Credential: Access key and AWS region being used (inย this case, us-east-1)
  • X-Amz-Date: Timestamp when the URL was created (Octoberย 6, 2025, atย 07:51:32ย UTC)
  • X-Amz-Expires: Duration the URL isย valid for inย seconds (86400 = 24ย hours)
  • X-Amz-SignedHeaders: Which HTTP headers are included inย the signature
  • X-Amz-Signature: Cryptographic proof ofย authorization

Toย sum itย up, the presigned URL essentially says, โ€œFor the next 24ย hours, anyone with this URL can upload part #47 ofย this specific multipart upload, and nothing else.โ€

Stepย 2: Upload each chunk inย parallel

With the presigned URLs created, the next step isย toย upload each chunk toย its assigned URL. The Upload API provides aย method toย doย this using the multipartUpload function.

Chunks are uploaded inย parallel toย maximize throughput.

// Upload multiple chunks simultaneously
const uploadPromises = presignedUrls.map((url, index) => {
  const chunk = getChunk(file, index, chunkSize);
  return uploadChunk(chunk, url);
});

// Wait for all chunks to complete
await Promise.all(uploadPromises);

Uploading 3-4 chunks simultaneously can triple orย quadruple your upload speed compared toย sequential uploads.

Stepย 3: Finalize and reassemble the file

When the last chunk uploads successfully, they are all combined toย form the original file onย the server. You can then retrieve the file using its UUID.

The server verifies all chunks arrived, reassembles them inย order, and returns the final file information, including:

  • File UUID
  • CDN URL for accessing the file
  • File size
  • MIME type
  • Storage status

Ifย youโ€™d like toย handle large file uploads byย building out this multipart process yourself, check out this articleย on how toย handle large file uploads.

Benefits ofย multipart and resumable uploads

Multipart uploads provide several advantages that make them ideal for handling large files.

Faster transfer speeds

Parallel chunk uploads can dramatically reduce transfer time. Instead ofย uploading 1GB sequentially atย 10ย MB/s (approximately 800ย seconds), you can upload four chunks simultaneously:

  • Sequential: 1ย GB รท 10ย MB/s = 800 seconds
  • Parallel (2ย chunks): 1ย GB รท (10ย MB/s ร— 2) = 400 seconds

Thatโ€™s aย 2xย speed improvement just from parallelization.

Upload reliability and better fault tolerance

With multipart uploads, aย network interruption does not necessarily mean starting the upload process all over again.

When aย chunk fails, you can retry that specific chunk. If, for instance, chunk 47ย out ofย 100ย fails, you only try that chunk again, not all 100.

This helps toย provide the ability toย pause and resume uploads without losing progress onย the file being uploaded.

Multipart uploads with Uploadcare

Uploadcare offers aย robust upload API that enables you toย seamlessly manage large files ofย upย toย 5TB with multipart uploads inย two ways: byย utilizing the File Uploader orย the HTTP Upload API (also available inย aย number ofย SDKs).

Using the Uploadcare File Uploader

Uploadcare File Uploader isย aย framework-agnostic component that handles file uploads with any JavaScript framework. The File Uploader automatically manages multipart uploads for large files without any additional configuration.

Instead ofย managing chunking and retries manually, the File Uploader does itย automatically soย you can focus onย your app logic, not your infrastructure.

Anย example ofย integrating the File Uploader inย aย JavaScript application looks like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link 
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@1/web/uc-file-uploader-regular.min.css" 
    />
    <script type="module">
      import * as UC from 'https://cdn.jsdelivr.net/npm/@uploadcare/file-uploader@1/web/file-uploader.min.js';
      UC.defineComponents(UC);
    </script>
  </head>
  <body>
    <uc-config 
      ctx-name="my-uploader" 
      pubkey="demopublickey" 
      multiple
    ></uc-config>
    
    <uc-file-uploader-regular
      ctx-name="my-uploader"
    ></uc-file-uploader-regular>
    
    <uc-upload-ctx-provider 
      ctx-name="my-uploader"
    ></uc-upload-ctx-provider>
  
    <script>
      document.addEventListener('DOMContentLoaded', () => {
        const ctx = document.querySelector('uc-upload-ctx-provider')
    
        ctx.addEventListener('file-upload-success', e => {
          console.log(e);
        });
      });
    </script>
  </body>
</html>

The code above has the following configurations:

  • ctx-name: Toย create aย unique context for linking all the file uploader components together
  • pubkey: Anย Uploadcare Public API key that you can find inย your projectโ€™s API settings.
  • multiple: Toย allow users toย upload multiple files.

The File Uploader automatically:

  • Splits large files into chunks.
  • Uploads chunks inย parallel.
  • Resumes failed uploads.
  • Provides progress tracking.
  • Handles all error recovery.

Using the Uploadcare Upload API for multipart uploads

Ifย you want more control over the file upload process, Uploadcare providesย an Upload API available inย various SDKs, including JavaScript, Python, PHP, Ruby, and more.

Hereโ€™s how toย implement the Upload API using the JavaScript SDK:

Stepย 1: Set upย aย project and install dependencies

Run the command below toย create aย new directory.

mkdir multipart-uploads
cd multipart-uploads

Inside the multipart-uploads directory, initialize aย new Node.js project.

npm init -y

This creates a package.json file inย your project directory with default settings.

Next, install the required dependencies.

npm install express multer @uploadcare/upload-client

The express package will create the Node.js server, multer will handle the multipart/form-data forms and @uploadcare/upload-client communicates with Uploadcareโ€™s server for file uploads.

For live reloading during development, install nodemon asย aย dev dependency.

npm install nodemon --save-dev

Then, update the scripts object in package.json:

{
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  }
}

Also add a type field toย useย ES modules:

{
  "type": "module"
}

Next, create an index.js file inย the root directory and add the following code:

import express from 'express';
import multer from 'multer';

const app = express();
const PORT = 3000;

// Store uploaded files in memory
const upload = multer();

// Serve static files for the HTML page
app.use(express.static('public'));

// File upload endpoint
app.post('/upload', upload.single('file'), async (req, res) => {
  try {
    if (!req.file) {
      return res.status(400).json({ error: 'No file uploaded' });
    }
    
    // File uploading logic will be here
    
  } catch (error) {
    console.error('Error uploading file:', error);
    res.status(500).json({
      success: false,
      message: 'File upload failed',
      error: error.message,
    });
  }
});

app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});

This code sets upย anย express server that listens onย port 3000 and uses the Multer middleware toย retrieve the file when aย request isย made toย the /upload endpoint.

Stepย 2: Create the frontend upload form

Create a public directory and add an index.html file.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Upload</title>
  </head>
  <body>
    <h1>Large file uploads</h1>
    <form action="/upload" method="post" enctype="multipart/form-data">
      <input type="file" name="file" required placeholder="Select file" />
      <button type="submit">Upload</button>
    </form>
  </body>
</html>

Stepย 3: Implement multipart upload inย the backend

Now letโ€™s implement multipart uploading with Uploadcareโ€™s JavaScript SDK.

Initialize the Uploadcare client

First, import the Uploadcare Upload SDK and initialize itย with your Public API key.

import { UploadClient } from '@uploadcare/upload-client';

const client = new UploadClient({ 
  publicKey: 'YOUR_PUBLIC_KEY' 
});

Replace YOUR_PUBLIC_KEY with your Uploadcare Public API key. You can find your Public API key inย your Uploadcare dashboard.

Start the multipart upload

Inside the try block inย the file upload endpoint, add the following code:

// Step 1: Start multipart upload
const startResult = await client.multipartStart(req.file.size, {
  fileName: req.file.originalname,
  contentType: req.file.mimetype,
  multipartChunkSize: 10 * 1024 * 1024, // 10 MB chunks
});

console.log('Multipart upload started:', {
  uuid: startResult.uuid,
  totalParts: startResult.parts.length,
  fileName: req.file.originalname,
  fileSize: req.file.size
});

Hereโ€™s what this code does:

  • Sends aย request toย Uploadcareโ€™s server toย start uploading aย large file using the client.multipartStart.
  • Provides necessary details such asย file size, filename, and chunk size.

The multipartChunkSize parameter determines how many URLs toย generate based onย the file size (default: 5ย MB).

For example, aย 50ย MB file with a multipartChunkSize ofย 10ย MB will generate five presigned URLs, one for each chunk.

The request returns anย object containing:

{
  uuid: '5eef12e3-e72a-4bf5-b68a-89953e81c7db',
  parts: [
    'https://uploadcare.s3-accelerate.amazonaws.com/...',
    'https://uploadcare.s3-accelerate.amazonaws.com/...',
    // ... more presigned URLs
  ]
}

Where the uuid isย the unique identifier for the large file and parts array isย anย array ofย the presigned URLs toย upload each parts (chunks) ofย the file

Upload each chunk

Using the presigned URLs from the multipartStart response, send upload requests for each chunk.

// Step 2: Upload file parts using the presigned URLs
const uploadPromises = startResult.parts.map(
  async (presignedUrl, index) => {
    const partSize = 10 * 1024 * 1024; // Must match multipartChunkSize
    const start = index * partSize;
    const end = Math.min(start + partSize, req.file.size);

    const chunk = req.file.buffer.subarray(start, end);
    
    console.log(`Uploading chunk ${index + 1}/${startResult.parts.length}`);
    
    return await client.multipartUpload(chunk, presignedUrl);
  }
);

// Wait for all chunks to upload
await Promise.all(uploadPromises);
console.log('All chunks uploaded successfully');

Hereโ€™s what this code does:

  • Creates an uploadPromises array that loops through the presigned URLs.
  • Calculates the start and end positions ofย the chunk using partSize (same as multipartChunkSize) for each URL.
  • Slices each chunk from the original file using the buffer.subarray method.
  • Sends each chunk toย its respective presigned URL using the multipartUpload method.
  • Uses Promise.all toย execute all upload requests inย parallel for maximum speed.

Complete the upload

Once all parts have uploaded successfully, finalize the upload onย the server.

// Step 3: Complete multipart upload
const completeResult = await client.multipartComplete(startResult.uuid);

console.log('Upload completed:', {
  uuid: completeResult.uuid,
  isReady: completeResult.is_ready,
  isStored: completeResult.is_stored,
  size: completeResult.size
});

// Verify the upload succeeded
if (!completeResult.is_ready || !completeResult.is_stored) {
  throw new Error('Upload verification failed');
}

// Send success response
res.status(200).json({
  success: true,
  message: 'File uploaded successfully',
  uuid: completeResult.uuid,
  fileUrl: `https://ucarecdn.com/${completeResult.uuid}/`,
  fileName: completeResult.original_filename,
  fileSize: completeResult.size,
  mimeType: completeResult.mime_type,
  isStored: completeResult.is_stored,
});

The multipartComplete method finalizes the upload onย the server and accepts the uuid from the multipartStart response. Itย returns the complete file information that you can use toย access the uploaded file.

Atย this point, your large file isย safely uploaded, verified, and accessible via its unique CDN URL, ready toย beย served orย processed further.

Stepย 4: Run and test your application

Toย run the application, start the development server.

npm run dev

Open your browser and navigate to http://localhost:3000. You should see the upload form. Try uploading aย large file (100+ย MB), and onย the server logs, you should see the multipart upload process inย action.

Multipart upload process inย server logsMultipart upload process inย server logs

Best practices for implementing multipart uploads

When using the Uploadcare multipart upload feature, consider using these tips toย handle large files effectively.

Choose appropriate chunk sizes

Chunk size affects upload performance and reliability, soย make sure youโ€™re optimizing your chunk size based onย the size ofย the file being uploaded.

Hereโ€™s anย example ofย how this could beย implemented:

function calculateOptimalChunkSize(fileSize) {
  if (fileSize < 100 * 1024 * 1024) { // < 100 MB
    return 5 * 1024 * 1024; // 5 MB chunks
  } else if (fileSize < 1024 * 1024 * 1024) { // < 1 GB
    return 10 * 1024 * 1024; // 10 MB chunks
  } else if (fileSize < 10 * 1024 * 1024 * 1024) { // < 10 GB
    return 25 * 1024 * 1024; // 25 MB chunks
  } else {
    return 50 * 1024 * 1024; // 50 MB chunks
  }
}

Aย general guideline you can follow when chunking aย fileย is:

  • 5-10ย MB: Good for most use cases; balances speed and reliability.
  • 10-25ย MB: Better for large files onย fast connections.
  • 25-50ย MB: Only for very large files (10ย GB+) onย stable, fast networks.

Using smaller chunks increases the number ofย HTTP requests but provides finer control during retries. Inย contrast, larger chunks decrease overall request overheads but raise the costs associated with retries.

Implement retry logic effectively

The Uploadcare Upload API byย default includes retry logic for throttled requests and unstable network connections when uploading chunks.

You can set how many times retries can beย made byย entering the following values when you start the multipart upload:

const startResult = await client.multipartStart(req.file.size, {
  store: 'auto',
  fileName: req.file.originalname,
  multipartChunkSize: chunkSize
  retryNetworkErrorMaxTimes: 3
  retryThrottledRequestMaxTimes: 2
});

retryNetworkErrorMaxTimes sets the maximum number ofย attempts toย retry requests that failed with aย network error.

retryThrottledRequestMaxTimes sets the maximum number ofย attempts toย retry throttled requests.

Validate completed uploads

Always confirm that the multipart upload has been successful before displaying success messages toย your users.

const completeResult = await client.multipartComplete(startResult.uuid);

// Verify the upload
if (!completeResult.isReady || !completeResult.isStored) {
  throw new Error('Upload verification failed - file not ready or stored');
}

// Confirm file size matches
if (completeResult.size !== req.file.size) {
  throw new Error(
    `File size mismatch: expected ${req.file.size}, got ${completeResult.size}`
  );
}

console.log('Upload verified successfully');

Provide clear error messages

Give your users concise error messages that explain why anย upload failed and let them know when they need toย take action.

try {
  // Upload logic
} catch (error) {
  let userMessage = 'File upload failed. Please try again.';
  let status = 500;

  switch (error.code || error.statusCode) {
    case 'NETWORK_ERROR':
      userMessage = 'Network connection lost. Please check your internet and try again.';
      status = 503;
      break;
    case 'TIMEOUT_ERROR':
      userMessage = 'Upload timed out. Please try uploading a smaller file or check your connection.';
      status = 408;
      break;
    case 'FILE_TOO_LARGE':
      userMessage = 'File is too large. Maximum file size is 5 GB.';
      status = 400;
      break;
    default:
      break;
  }

  res.status(status).json({
    success: false,
    message: userMessage,
    technicalError: error.message || 'Unknown error',
  });
}

Conclusion

Multipart uploads are the foundation ofย reliable file handling atย scale. With Uploadcareโ€™s File Uploader and Upload API, you can implement this workflow inย minutes gaining speed, stability, and seamless scalability out ofย the box.

For more information, check out the Uploadcare documentation and explore additional features like image processing, document conversion, image CDN, and video CDN toย further enhance your file-uploading capabilities.

Ready to get started?

Join developers who use Uploadcare to build fileย handling quickly andย reliably.

Sign up for free