vue实现大文件切片上传

在前端上传 大文件(比如几百 MB 或几 GB 时,一般会用 文件切片(chunk upload)+ 断点续传 的方式。核心思路是:

  1. 前端把文件 按固定大小切成多个 chunk
  2. 逐个上传 chunk
  3. 服务端 按顺序合并 chunk
  4. 如果中断,可以 只上传缺失的 chunk

一、实现流程(大文件切片上传)

流程通常是:

复制代码
选择文件
   ↓
计算文件hash(可选,用于秒传)
   ↓
切片 file.slice()
   ↓
并发上传 chunk
   ↓
服务端记录 chunk
   ↓
全部上传完成
   ↓
请求服务端 merge

常见参数:

复制代码
chunkIndex   当前分片序号
chunkSize    分片大小
totalChunks  分片总数
fileHash     文件hash

二、Vue 实现案例

1 选择文件

html 复制代码
<input type="file" @change="handleFileChange" />
js 复制代码
data() {
  return {
    file: null
  }
},
methods: {
  handleFileChange(e) {
    this.file = e.target.files[0]
  }
}

三、文件切片

假设每片 5MB

js 复制代码
const CHUNK_SIZE = 5 * 1024 * 1024

function createChunks(file) {
  const chunks = []
  let start = 0

  while (start < file.size) {
    chunks.push(file.slice(start, start + CHUNK_SIZE))
    start += CHUNK_SIZE
  }

  return chunks
}

返回:

复制代码
[chunk0, chunk1, chunk2 ...]

四、上传切片

js 复制代码
async uploadFile() {

  const chunks = createChunks(this.file)

  const requests = chunks.map((chunk, index) => {

    const formData = new FormData()

    formData.append("file", chunk)
    formData.append("index", index)
    formData.append("fileName", this.file.name)
    formData.append("total", chunks.length)

    return fetch("/upload", {
      method: "POST",
      body: formData
    })

  })

  await Promise.all(requests)

  await this.mergeChunks()

}

五、通知服务端合并

js 复制代码
async mergeChunks() {

  await fetch("/merge", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      fileName: this.file.name
    })
  })

}

六、服务端逻辑(核心思路)

无论你是用 Node.js / Java / Go,都一样。

上传 chunk

复制代码
/upload

保存为

复制代码
/upload
   fileHash/
       0
       1
       2
       3

合并文件

复制代码
/merge

伪代码

js 复制代码
for (let i = 0; i < total; i++) {
  读取 chunk i
  append 到最终文件
}

七、优化(生产级必须做)

1 并发控制(避免100个请求)

推荐 5~10 并发

js 复制代码
async function uploadChunks(chunks, limit = 5) {

}

2 文件 hash(实现秒传)

使用

复制代码
spark-md5

计算 hash

js 复制代码
hash = md5(file)

服务器如果存在

复制代码
直接返回 秒传成功

3 断点续传

流程:

  1. 上传前询问服务器

    /check

返回

复制代码
已上传 chunks = [0,1,4,5]
  1. 前端只上传

    [2,3]


4 上传进度

js 复制代码
xhr.upload.onprogress = (e)=>{
  progress = e.loaded / e.total
}

八、完整 Vue 示例(简化版)

js 复制代码
async uploadFile() {

  const CHUNK_SIZE = 5 * 1024 * 1024
  const file = this.file

  const chunks = []
  let start = 0

  while (start < file.size) {
    chunks.push(file.slice(start, start + CHUNK_SIZE))
    start += CHUNK_SIZE
  }

  for (let i = 0; i < chunks.length; i++) {

    const formData = new FormData()

    formData.append("file", chunks[i])
    formData.append("index", i)
    formData.append("total", chunks.length)
    formData.append("fileName", file.name)

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

  }

  await fetch("/merge", {
    method: "POST",
    body: JSON.stringify({ fileName: file.name })
  })

}
相关推荐
桔筐20 小时前
Axios 从入门到实战封装全解析(附异步/拦截器/生命周期)
vue.js
甄心爱学习20 小时前
【项目实训】法律文书智能摘要系统2
前端·javascript·vue.js
华科易迅20 小时前
Vue通过Ajax获取后台路由信息
vue.js·ajax·okhttp
cch891820 小时前
PHP vs Vue.js:后端与前端的终极对比
前端·vue.js·php
我命由我1234520 小时前
Vue3 开发中,字符串中的 <br\> 标签被直接当作文本显示出来了,而不是被解析为 HTML 换行标签
开发语言·前端·javascript·vue.js·html·ecmascript·html5
北风toto21 小时前
Vue多文件学习项目综合案例——面经基础版,黑马vue教程
javascript·vue.js·学习
徐小夕1 天前
我用 AI 撸了个开源"万能预览器":浏览器直接打开 Office、CAD 和 3D 模型
前端·vue.js·github
前端Hardy1 天前
字节/腾讯内部流出!Claude Code 2026王炸玩法!效率暴涨10倍
前端·javascript·vue.js
逆光如雪2 天前
移动端卡片边框怎么做高级?我用 CSS 实现了设计师的刁钻要求
前端·css·vue.js
莹宝思密达2 天前
地图显示西安经济开发区边界线-2023.12
前端·vue.js·数据可视化