Front‑End Large File Upload: Principles, Key Features, and Using the enlarge‑file‑upload Library

This article explains the concept of large file upload in front‑end development, outlines the problems it solves, compares it with ordinary uploads, details essential implementation steps such as chunking, parallelism, resume, and integrity checks, and demonstrates practical usage of the enlarge‑file‑upload library across vanilla JavaScript, Vue2, Vue3, and React.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Front‑End Large File Upload: Principles, Key Features, and Using the enlarge‑file‑upload Library

1. What Is Large File Upload?

(1) Definition

Large file upload means transferring very large files (tens of megabytes to gigabytes) from the client browser to a server, which traditional single‑request uploads cannot handle reliably because of network instability, time‑outs, and heavy server resource consumption.

(2) Problems Solved by Large File Upload

Unstable network: Chunked or resumable uploads can survive temporary disconnections and continue where they left off.

Server resource limits: By sending small pieces, memory and CPU usage on the server stay low, preventing crashes.

User experience: Progress bars, speed indicators, and resumable uploads keep users informed and avoid re‑uploading the whole file after an interruption.

File integrity verification: Hash checks ensure the uploaded file matches the original data.

(3) Advantages Over Ordinary Uploads

Can handle GB‑scale files through slicing.

Supports breakpoint resume, saving time and bandwidth.

Parallel uploading of multiple slices speeds up transfer.

Optimises server resource usage by processing small chunks.

Provides precise progress monitoring.

2. Key Front‑End Implementation Points

To implement large file upload on the front end you need to address the following features:

(1) File Chunking

Split the file into fixed‑size pieces (e.g., 1 MB or 5 MB) using File.slice() from the File API.

(2) Chunk Upload

Send each slice to the server via XMLHttpRequest or the Fetch API. Multiple slices can be uploaded concurrently for higher throughput.

(3) Resumable Upload

Persist the list of already‑uploaded chunks (e.g., via a hash or index) so that after a network break the client can continue uploading the remaining pieces.

(4) Progress Monitoring

Use the progress event of XMLHttpRequest or a ReadableStream with Fetch to calculate and display the overall percentage.

(5) File Integrity Check

After the whole file is uploaded, compute a hash (MD5, SHA‑256, etc.) on the client with FileReader and compare it with the server‑side hash.

(6) Error Handling & Retry

Implement per‑chunk retry logic and global error handling to recover from network or server errors.

(7) Concurrency Control

Limit the number of simultaneous requests (e.g., a pool of 5) to avoid saturating bandwidth or overloading the server.

(8) UX Optimisation

Show progress bars, upload speed, remaining time, and support drag‑and‑drop, multi‑file selection, and batch uploads.

(9) Security Considerations

Validate file type and size on the client, enforce HTTPS, and perform server‑side checks to prevent malicious uploads.

3. Recommended Library – enlarge-file-upload

Writing a full uploader from scratch is time‑consuming. The enlarge-file-upload package implements all the above features and works out‑of‑the‑box with Vue 2, Vue 3, React, or plain JavaScript.

Installation

npm install enlarge-file-upload

Run the command in your project directory; the library will be added to package.json.

Common Parameters

file

: the File object to upload (required). serverUrl: endpoint that receives the chunk data. onProgress: callback receiving the overall progress percentage. onSuccess: called when the whole file finishes uploading. onError: receives error information for debugging.

Usage Examples

Vanilla JavaScript (jQuery) Example

<!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>
  <input type="file" id="fileInput" />
  <button id="pauseButton">暂停上传</button>
  <button id="resumeButton">继续上传</button>
  <div id="progress">上传进度:0%</div>
  <div id="speed">上传速度:0 MB/s</div>
  <script src="https://cdn.jsdelivr.net/npm/enlarge-file-upload/dist/upload.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/axios"></script>
  <script>
    async function uploadFunction({ chunk, index, hash, cancelToken }) {
      const formData = new FormData();
      formData.append('chunk', chunk);
      formData.append('hash', hash);
      formData.append('index', index);
      await axios.post('http://localhost:3000/api/users', formData, { cancelToken });
    }
    const config = {
      chunkSize: 5 * 1024 * 1024, // 5 MB
      concurrency: 5,
      maxRetries: 3,
      uploadFunction,
      onProgress: (progress) => {
        document.getElementById('progress').innerText = `上传进度:${progress.toFixed(2)}%`;
      },
      onSuccess: () => { console.log('上传完毕'); },
      onSpeed: (speed) => { document.getElementById('speed').innerText = `上传速度:${speed}`; },
    };
    const { upload, pause, resume, state } = createUploader(config);
    const fileInput = document.getElementById('fileInput');
    fileInput.addEventListener('change', () => {
      const file = fileInput.files[0];
      upload(file);
    });
    document.getElementById('pauseButton').addEventListener('click', pause);
    document.getElementById('resumeButton').addEventListener('click', resume);
  </script>
</body>
</html>

Vue 3 Example

<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <button @click="uploadFile">上传文件</button>
  </div>
</template>
<script setup>
import { ref } from 'vue';
import EnlargeFileUpload from 'enlarge-file-upload';
const fileRef = ref(null);
const handleFileChange = (e) => { fileRef.value = e.target.files[0]; };
const uploadFile = () => {
  if (fileRef.value) {
    const uploader = new EnlargeFileUpload({
      file: fileRef.value,
      serverUrl: 'http://your-server-url.com/upload',
      onProgress: (p) => console.log(`上传进度: ${p}%`),
      onSuccess: () => console.log('文件上传成功'),
      onError: (e) => console.error('文件上传失败', e),
    });
    uploader.start();
  }
};
</script>

Vue 2 Example

<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <button @click="handlePause">暂停上传</button>
    <button @click="handleResume">继续上传</button>
    <div>上传进度:{{ progress.toFixed(2) }}%</div>
    <div>上传速度:{{ speed }}</div>
  </div>
</template>
<script>
import Vue from 'vue';
import { createUploader } from 'enlarge-file-upload';
import axios from 'axios';
export default Vue.extend({
  data() {
    return { progress: 0, speed: '0 MB/s', uploader: null };
  },
  methods: {
    async uploadFunction({ chunk, index, hash, cancelToken }) {
      const formData = new FormData();
      formData.append('chunk', chunk);
      formData.append('hash', hash);
      formData.append('index', index.toString());
      await axios.post('http://localhost:3000/api/users', formData, { cancelToken });
    },
    handleFileChange(e) {
      const file = e.target.files?.[0];
      if (file && this.uploader) this.uploader.upload(file);
    },
    handlePause() { if (this.uploader) this.uploader.pause(); },
    handleResume() { if (this.uploader) this.uploader.resume(); },
  },
  created() {
    const uploaderConfig = {
      chunkSize: 5 * 1024 * 1024,
      concurrency: 5,
      maxRetries: 3,
      uploadFunction: this.uploadFunction,
      onProgress: (v) => { this.progress = v; },
      onSuccess: () => console.log('上传完毕'),
      onSpeed: (s) => { this.speed = s; },
    };
    this.uploader = createUploader(uploaderConfig);
  },
});
</script>

React Example

import React, { useRef, useMemo } from 'react';
import EnlargeFileUpload from 'enlarge-file-upload';

const FileUploadComponent = () => {
  const fileInputRef = useRef(null);
  const uploadFile = () => {
    const file = fileInputRef.current.files[0];
    if (file) {
      const uploader = useMemo(() => new EnlargeFileUpload({
        file,
        serverUrl: 'http://your-server-url.com/upload',
        onProgress: (p) => console.log(`上传进度: ${p}%`),
        onSuccess: () => console.log('文件上传成功'),
        onError: (e) => console.error('文件上传失败', e),
      }), [file]);
      uploader.start();
    }
  };
  return (
    <div>
      <input type="file" ref={fileInputRef} />
      <button onClick={uploadFile}>上传文件</button>
    </div>
  );
};
export default FileUploadComponent;

React Hook Wrapper

import { useState, useCallback, useMemo } from 'react';
import { createUploader } from 'enlarge-file-upload';
import axios from 'axios';

export default function useFileUploader() {
  const [progress, setProgress] = useState(0);
  const [speed, setSpeed] = useState('0 MB/s');

  const uploadFunction = useCallback(async ({ chunk, index, hash, cancelToken }) => {
    const formData = new FormData();
    formData.append('chunk', chunk);
    formData.append('hash', hash);
    formData.append('index', index);
    await axios.post('http://localhost:3000/api/users', formData, { cancelToken });
  }, []);

  const uploaderConfig = useMemo(() => ({
    chunkSize: 5 * 1024 * 1024,
    concurrency: 5,
    maxRetries: 3,
    uploadFunction,
    onProgress: (p) => setProgress(p),
    onSuccess: () => console.log('Upload complete'),
    onSpeed: (s) => setSpeed(s),
  }), [uploadFunction]);

  const uploader = useMemo(() => createUploader(uploaderConfig), [uploaderConfig]);

  const uploadFile = useCallback((file) => uploader?.upload(file), [uploader]);
  const pauseUpload = useCallback(() => uploader?.pause(), [uploader]);
  const resumeUpload = useCallback(() => uploader?.resume(), [uploader]);

  return { progress, speed, uploadFile, pauseUpload, resumeUpload };
}

Large file upload is a crucial technique in front‑end development; understanding its principles and using a robust library like enlarge-file-upload can greatly improve user experience and reliability.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaScriptresumable uploadprogress barLarge File Uploadfile chunkingenlarge-file-upload
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.