vue实现分段上传
分段上传的实现原理
分段上传(Chunked Upload)是将大文件分割成多个小块分别上传,最后在服务端合并的技术。这种方式能有效解决大文件上传超时、网络不稳定等问题,同时支持断点续传和进度显示。
前端实现步骤
安装必要的依赖库(如axios):
npm install axios
创建文件分片函数:
function createFileChunks(file, chunkSize = 5 * 1024 * 1024) {
const chunks = []
let start = 0
while (start < file.size) {
chunks.push({
file: file.slice(start, start + chunkSize),
filename: file.name
})
start += chunkSize
}
return chunks
}
上传组件示例:
<template>
<input type="file" @change="handleFileChange" />
<button @click="uploadFile">上传</button>
<div>进度:{{ progress }}%</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
file: null,
progress: 0
}
},
methods: {
handleFileChange(e) {
this.file = e.target.files[0]
},
async uploadFile() {
if (!this.file) return
const chunks = createFileChunks(this.file)
const total = chunks.length
const uploads = chunks.map((chunk, index) => {
const formData = new FormData()
formData.append('file', chunk.file)
formData.append('filename', chunk.filename)
formData.append('chunkIndex', index)
formData.append('totalChunks', total)
return axios.post('/upload', formData, {
onUploadProgress: (progressEvent) => {
const percent = Math.round(
(progressEvent.loaded / progressEvent.total) * 100
)
this.progress = Math.min(
100,
((index * 100) + percent) / total
)
}
})
})
await Promise.all(uploads)
await axios.post('/merge', {
filename: this.file.name,
totalChunks: total
})
}
}
}
</script>
服务端处理要点
Node.js 示例(使用Express):
const express = require('express')
const multer = require('multer')
const fs = require('fs')
const path = require('path')
const app = express()
const upload = multer({ dest: 'temp/' })
app.post('/upload', upload.single('file'), (req, res) => {
const { filename, chunkIndex } = req.body
const tempPath = path.join('temp', `${filename}-${chunkIndex}`)
fs.renameSync(req.file.path, tempPath)
res.send({ success: true })
})
app.post('/merge', (req, res) => {
const { filename, totalChunks } = req.body
const writeStream = fs.createWriteStream(`uploads/${filename}`)
for (let i = 0; i < totalChunks; i++) {
const chunkPath = path.join('temp', `${filename}-${i}`)
const chunk = fs.readFileSync(chunkPath)
writeStream.write(chunk)
fs.unlinkSync(chunkPath)
}
writeStream.end()
res.send({ success: true })
})
app.listen(3000)
优化建议
实现文件哈希校验可以在分片前计算文件唯一标识,避免重复上传。使用Web Worker处理大文件计算防止UI阻塞。
添加断点续传功能需要服务端支持查询已上传分片,前端根据返回结果跳过已上传部分。典型做法是在分片上传前先发送查询请求。

进度显示优化可以考虑分片进度和整体进度分开显示,使用更直观的进度条组件替代简单百分比。






