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 })
  })

}
相关推荐
予你@。2 小时前
Vue 实现:点击按钮将 HTML 导出为图片(完整教程)
javascript·vue.js·html
青莳吖2 小时前
vue封装el-table通用的可编辑单元格,如下拉框、输入框
前端·javascript·vue.js
RDCJM3 小时前
Spring Boot + Vue 全栈开发实战指南
vue.js·spring boot·后端
kuntli13 小时前
Vue生命周期全解析
vue.js
小一梦14 小时前
宝塔面板单域名部署多个 Vue 项目:从路径冲突到完美共存
服务器·javascript·vue.js
只能是遇见14 小时前
SpringBoot + vue 管理系统
vue.js·spring boot·后端
发现一只大呆瓜16 小时前
Vue-Vue Router核心原理+实战用法全解析
前端·vue.js·面试
米丘19 小时前
vue-router v5.x createRouter 是创建路由实例?
前端·vue.js