DEV Community

Raj Aryan
Raj Aryan

Posted on

1

How to Build a Multi-Part Uploader System in JavaScript for Faster File Uploads

Introduction

In today’s digital world, uploading large files is a common requirement for many web applications. Whether it’s videos, high-resolution images, or large datasets, users expect fast and reliable uploads. However, handling large files can be challenging due to network instability, server limitations, and browser constraints. This is where a multi-part uploader system comes into play.

In this blog post, we’ll explore how to build a multi-part uploader system in JavaScript. This system will split large files into smaller chunks, upload them in parallel, and reassemble them on the server. By the end of this guide, you’ll have a robust solution for handling large file uploads efficiently.


What is a Multi-Part Uploader?

A multi-part uploader is a technique that breaks down large files into smaller, manageable chunks. These chunks are uploaded independently, often in parallel, to the server. Once all the chunks are uploaded, the server reassembles them into the original file. This approach offers several benefits:

  1. Faster Uploads: Uploading smaller chunks in parallel speeds up the process.
  2. Resumable Uploads: If the upload fails, only the failed chunks need to be re-uploaded.
  3. Better Reliability: Smaller chunks are less likely to fail due to network issues.
  4. Scalability: Reduces server load by handling smaller pieces of data.

How to Build a Multi-Part Uploader in JavaScript

Let’s dive into the steps to create a multi-part uploader system using JavaScript. We’ll use the Fetch API for uploading chunks and a Node.js server to handle the file reassembly.


Step 1: Split the File into Chunks

The first step is to split the file into smaller chunks. JavaScript’s File API makes this easy.

function splitFile(file, chunkSize) {
  const chunks = [];
  let start = 0;

  while (start < file.size) {
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);
    chunks.push(chunk);
    start = end;
  }

  return chunks;
}
Enter fullscreen mode Exit fullscreen mode

This function takes a File object and a chunkSize (in bytes) as input and returns an array of chunks.


Step 2: Upload Chunks in Parallel

Once the file is split into chunks, we can upload them in parallel using the Fetch API.

async function uploadChunks(chunks, uploadUrl) {
  const uploadPromises = chunks.map((chunk, index) => {
    const formData = new FormData();
    formData.append('file', chunk);
    formData.append('chunkIndex', index);
    formData.append('totalChunks', chunks.length);

    return fetch(uploadUrl, {
      method: 'POST',
      body: formData,
    });
  });

  await Promise.all(uploadPromises);
  console.log('All chunks uploaded successfully!');
}
Enter fullscreen mode Exit fullscreen mode

This function uploads each chunk to the server using a POST request. The chunkIndex and totalChunks are sent as metadata to help the server reassemble the file.


Step 3: Reassemble the File on the Server

On the server side (using Node.js and Express), we’ll handle the incoming chunks and reassemble them into the original file.

const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();

app.use(express.json());

app.post('/upload', (req, res) => {
  const chunk = req.files.file;
  const chunkIndex = req.body.chunkIndex;
  const totalChunks = req.body.totalChunks;

  const uploadDir = path.join(__dirname, 'uploads');
  if (!fs.existsSync(uploadDir)) {
    fs.mkdirSync(uploadDir);
  }

  const chunkPath = path.join(uploadDir, `chunk-${chunkIndex}`);
  fs.writeFileSync(chunkPath, chunk.data);

  if (chunkIndex == totalChunks - 1) {
    // All chunks uploaded, reassemble the file
    const filePath = path.join(uploadDir, 'final-file');
    for (let i = 0; i < totalChunks; i++) {
      const chunkPath = path.join(uploadDir, `chunk-${i}`);
      fs.appendFileSync(filePath, fs.readFileSync(chunkPath));
      fs.unlinkSync(chunkPath); // Delete the chunk after appending
    }
    console.log('File reassembled successfully!');
  }

  res.sendStatus(200);
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

This server code saves each chunk to a temporary directory and reassembles them once all chunks are uploaded.


Step 4: Handle Errors and Retries

To make the uploader more robust, add error handling and retry logic for failed chunks.

async function uploadChunksWithRetry(chunks, uploadUrl, retries = 3) {
  const uploadPromises = chunks.map(async (chunk, index) => {
    for (let attempt = 1; attempt <= retries; attempt++) {
      try {
        const formData = new FormData();
        formData.append('file', chunk);
        formData.append('chunkIndex', index);
        formData.append('totalChunks', chunks.length);

        await fetch(uploadUrl, {
          method: 'POST',
          body: formData,
        });
        break; // Exit the retry loop if successful
      } catch (error) {
        if (attempt === retries) throw error;
        console.log(`Retrying chunk ${index}, attempt ${attempt}`);
      }
    }
  });

  await Promise.all(uploadPromises);
  console.log('All chunks uploaded successfully!');
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Building a multi-part uploader system in JavaScript is a powerful way to handle large file uploads efficiently. By splitting files into smaller chunks, uploading them in parallel, and reassembling them on the server, you can significantly improve upload speed, reliability, and user experience.

Whether you’re building a video-sharing platform, a cloud storage service, or any application that deals with large files, a multi-part uploader is a must-have feature. With the code examples provided in this post, you can easily implement this system in your own projects.


Call to Action

If you found this guide helpful, share it with your fellow developers! Have questions or suggestions? Leave a comment below or reach out to us on social media. Happy coding! 🚀


multi-part uploader, JavaScript file upload, large file upload, resumable upload, JavaScript Fetch API, Node.js file handling, parallel uploads, file chunking, web development, JavaScript tutorial.

By following this guide, you’ll not only improve your application’s file upload capabilities but also boost its performance and user satisfaction. Start implementing your multi-part uploader system today!

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay