这里我们用的的组件是antd-vue 的 upload 组件
upload 组件的自定义上传文件的方法
async customRequest(info) {
const buffer = await this.fileToBuffer(info.file) // 将文件对象转换成array buffer 格式
// 可以将文件按固定大小或者固定数量的方式进行切片,这里我们选择采用固定文件大小的方式,固定大小为2M
const chunkSize = 2 * 1024 * 1024 // 固定大小2M
const chunkList = [] // 保存所有切片的数组
const chunkListLength = Math.ceil(info.file.size / chunkSize) // 计算总共多个切片
const suffix = /\.([0-9A-z]+)$/.exec(info.file.name)[1] // 文件后缀名
// 根据文件内容生成 hash 值
const spark = new SparKMD5.ArrayBuffer()
spark.append(buffer)
const hash = spark.end()
this.hash = hash
// 生成切片,这里后端要求传递的参数为字节数据块(chunk)和每个数据块的文件名(fileName)
let curChunk = 0 // 切片时的初始位置
for (let i = 0; i < chunkListLength; i++) {
const item = {
chunk: info.file.slice(curChunk, curChunk + chunkSize),
fileName: `${hash}_${i}.${suffix}`, // 文件名规则按照 hash_1. 命名
}
curChunk += chunkSize
chunkList.push(item)
}
this.chunkList = chunkList
this.sendRequest()
},
// 将文件对象转换成array buffer格式
fileToBuffer(file) {
return new Promise((resolve, reject) => {
const fr = new FileReader()
fr.onload = (e) => {
resolve(e.target.result)
}
fr.readAsArrayBuffer(file)
fr.onerror = () => {
reject(new Error('转换文件格式发生错误'))
}
})
},
// 发送请求
sendRequest() {
const requestList = [] // 请求集合
this.chunkList.forEach((item, index) => {
const fn = () => {
const { id } = this.$route.query
const formData = new FormData()
formData.append('file', item.chunk)
formData.append('fileName', item.fileName)
const obj = {
url: '/pm/project/management/file/upload',
requestData: formData,
}
submitData(obj).then((res) => {
if (res.code === 0) {
// this.$message.success('上传成功')
}
})
}
requestList.push(fn)
})
let i = 0 // 记录发送的请求个数
const send = async () => {
// if ('暂停') return
if (i >= requestList.length) {
// 所有的chunk发送完毕,向后端发送合并文件的请求,告诉后端合并文件
this.sendComplete()
return
}
await requestList[i]()
i++
send()
}
send() // 发送请求
},