前端大文件切片上传
基本步骤
- 上传文件;
- 文件按需切割为不等分;
- 逐步切片请求;
- 创建FormData对象,为每一片数据添加上描述信息和添加序号;
- 发起请求(返回promise);
- 全部上传成功后,发起合并文件请求。
处理逻辑部分
import { getInfo, postInfo, uploadSlice, uploadEnd } from '../apis/index'
// 2.文件按需切割为不等分:默认0.5M分一片
const createThunck = (file, size = 1024 * 1024 * 0.5) => {
const result = [] //文件切片之后的数组
let cur = 0 //当前大小(位置)
while (cur < file.size) {
result.push({
sliceFile: file.slice(cur, cur + size)
})
cur += size
}
return result
}
// 1.上传文件
//选中文件后,e.target.files的值,当然,这个值是数组,我们需要他的第一个
//注意的就是使用 data 传递了一个参数,参数类型是 FromData。
const uploadFile = async (e) => {
const files = e.target.files
const fileList = createThunck(files?.[0], 1000)
const uuid = crypto.randomUUID()
// 3.逐步切片请求:切片请求
const uploadList = fileList.map((item, index) => {
const formData = new FormData() //定义上传数据
formData.append('fileChunk', item.sliceFile) //切片块数据
formData.append('fileChunkName', uuid + '@' + index) //切片块名称
formData.append('fileName', uuid + '@' + files[0].name) //文件名
return uploadSlice(formData)
})
//4.全部上传成功后,发起合并文件请求:所有切片上传成功后,发起文件合并请求
Promise.all(uploadList).then(res => {
console.log('上传成功');
uploadEnd({
fileList: files[0].name, //文件名
extname: files[0].name.split('.').slice(-1)[0] //文件后缀名
}).then(res => console.log(res.data))
})
.catch(err => {
console.log(err);
})
}
请求方法
import axios from "axios";
const BASE_URL = '/api'
export const uploadSlice = (file) => {
return axios({
url: '/upload_slice',
baseURL: BASE_URL,
method: 'post',
data: file,
onUploadProgress(progressEvent) {
let complete = (((progressEvent.loaded / progressEvent.total) * 100) | 0) + '%';
// console.log('上传 ' + complete);
}
})
}
export const uploadEnd = (data) => {
return axios({
url: '/upload_end',
baseURL: BASE_URL,
method: 'post',
data,
timeout: 5000,
})
}