当前位置:首页 > JavaScript

js实现分段上传

2026-03-15 19:47:32JavaScript

实现分段上传的基本思路

分段上传(Chunked Upload)通常用于大文件上传,将文件分割为多个小块依次上传,最后在服务器合并。这种方式能提高上传稳定性、支持断点续传,并减轻服务器压力。

前端代码实现

使用JavaScript的File对象和Blob.prototype.slice方法切割文件,通过FormData发送分片:

js实现分段上传

function uploadFile(file, chunkSize = 1024 * 1024) {
  const totalChunks = Math.ceil(file.size / chunkSize);
  let currentChunk = 0;

  const uploadNextChunk = () => {
    const start = currentChunk * chunkSize;
    const end = Math.min(start + chunkSize, file.size);
    const chunk = file.slice(start, end);

    const formData = new FormData();
    formData.append('chunk', chunk);
    formData.append('chunkIndex', currentChunk);
    formData.append('totalChunks', totalChunks);
    formData.append('fileName', file.name);

    fetch('/upload', {
      method: 'POST',
      body: formData
    }).then(response => {
      if (currentChunk < totalChunks - 1) {
        currentChunk++;
        uploadNextChunk();
      } else {
        console.log('Upload complete');
      }
    });
  };

  uploadNextChunk();
}

// 使用示例
document.getElementById('fileInput').addEventListener('change', (e) => {
  uploadFile(e.target.files[0]);
});

服务器端处理逻辑

以Node.js为例的简单合并逻辑:

js实现分段上传

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

const app = express();
const upload = multer({ dest: 'uploads/' });

app.post('/upload', upload.single('chunk'), (req, res) => {
  const { chunkIndex, totalChunks, fileName } = req.body;
  const tempPath = path.join(__dirname, 'temp', fileName);

  // 将分片追加到临时文件
  fs.appendFileSync(tempPath, fs.readFileSync(req.file.path));
  fs.unlinkSync(req.file.path);

  if (parseInt(chunkIndex) === parseInt(totalChunks) - 1) {
    // 全部分片上传完成,进行最终处理
    const finalPath = path.join(__dirname, 'uploads', fileName);
    fs.renameSync(tempPath, finalPath);
    res.json({ success: true });
  } else {
    res.json({ success: true });
  }
});

断点续传实现

需要记录已上传的分片信息:

// 前端记录已上传的分片
let uploadedChunks = new Set();

function resumeUpload(file, chunkSize) {
  // 从服务器获取已上传分片信息
  fetch('/getUploadedChunks?fileName=' + file.name)
    .then(res => res.json())
    .then(data => {
      uploadedChunks = new Set(data.uploadedChunks);
      startUpload(file, chunkSize);
    });
}

function startUpload(file, chunkSize) {
  // 跳过已上传的分片
  for (let i = 0; i < totalChunks; i++) {
    if (!uploadedChunks.has(i)) {
      uploadChunk(i);
      break;
    }
  }
}

进度显示实现

通过计算已上传分片比例显示进度:

function updateProgress(currentChunk, totalChunks) {
  const progress = Math.round((currentChunk + 1) / totalChunks * 100);
  document.getElementById('progress').textContent = `${progress}%`;
}

// 在每次分片上传成功后调用
updateProgress(currentChunk, totalChunks);

注意事项

  • 分片大小建议设置为1MB-5MB,过小会增加请求次数,过大可能失去分片意义
  • 服务器需要处理并发上传可能导致的文件顺序问题
  • 考虑添加文件MD5校验确保完整性
  • 临时文件需要定期清理机制

标签: 上传js
分享给朋友:

相关文章

vue实现文件的上传

vue实现文件的上传

文件上传的基本实现 在Vue中实现文件上传通常结合HTML的<input type="file">元素和FormData对象。通过监听文件选择事件获取文件对象,再通过AJAX或axios发…

js实现点击显示和隐藏

js实现点击显示和隐藏

实现点击显示和隐藏的JavaScript方法 使用classList.toggle切换类名 通过添加/移除CSS类控制元素的显示与隐藏,需提前在CSS中定义隐藏样式(如display: none)。…

js实现百叶窗

js实现百叶窗

使用CSS和JavaScript实现百叶窗效果 通过CSS动画和JavaScript事件监听可以实现百叶窗效果。核心思路是将内容区域分割为多个条状元素,通过控制它们的展开/折叠状态来模拟百叶窗。 &…

js实现vue路由

js实现vue路由

Vue 路由的基本实现 在 Vue.js 中实现路由功能通常使用 Vue Router 库。Vue Router 是 Vue.js 官方的路由管理器,用于构建单页面应用(SPA)。 安装 Vue R…

js实现正交

js实现正交

正交的概念 正交在数学和计算机科学中通常指两个向量垂直或线性无关。在编程中,正交性常被用于设计模块化、低耦合的系统。 向量正交判断 判断两个向量是否正交可以通过点积是否为0来实现: fun…

js怎么实现异步

js怎么实现异步

异步实现方法 JavaScript中实现异步操作主要通过以下几种方式: Promise Promise是ES6引入的异步解决方案,用于处理异步操作的成功或失败状态。 const promise =…