You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

117 lines
4.1 KiB

import md5 from 'js-md5'
import preview from './preview'
// 分片上传
/*
* 分片上传函数 支持多个文件
* @param options
* options.file 表示源文件
* options.pieceSize 表示需要分片的大小 默认是5m
* options.chunkUrl 分片上传的后端地址
* options.fileUrl 整个文件的上传地址
* options.renwuId 文件绑定的任务Id
* options.type 文件类型容器原始资料、管道无损分项
* success 成功回调
* error 失败回调
*/
export const uploadByPieces = async({ files, chunkUrl, fileUrl, pieceSize, renwuId, type, progress, success, error }) => {
if (!files || !files.length) return
// 上传过程中用到的变量
const fileList = [] // 总文件列表
let progressNum = 1 // 进度
let AllChunk = 0 // 所有文件的chunk数之和
let AllFileSize = 0 // 所有文件size
let successAllCount = 0 // 上传成功的片数
// 获取md5
const readFileMD5 = async(files) => {
// 读取每个文件的md5
await files.map((file, index) => {
const fileReaderInstance = new FileReader()
fileReaderInstance.readAsBinaryString(file)
fileReaderInstance.addEventListener('load', async e => {
const fileBlob = e.target.result
const fileMD5 = await md5(fileBlob)
if (!fileList.some((arr) => arr.md5 === fileMD5)) {
await fileList.push({ md5: fileMD5, name: file.name, file })
AllFileSize = AllFileSize + file.size
}
if (index === files.length - 1) await readChunkMD5(fileList)
}, false)
})
}
const getChunkInfo = (file, currentChunk, chunkSize) => {
const start = currentChunk * chunkSize
const end = Math.min(file.size, start + chunkSize)
const chunk = file.slice(start, end)
return { start, end, chunk }
}
// 针对每个文件进行chunk处理
const readChunkMD5 = async(fileList) => {
await fileList.map(async(currentFile) => {
const chunkSize = pieceSize * 1024 * 1024 // 5MB一片
const chunkCount = Math.ceil(currentFile.file.size / chunkSize) // 总片数
AllChunk = AllChunk + chunkCount // 计算全局chunk数
// 针对单个文件进行chunk上传
for (let i = 0; i < chunkCount; i++) {
const { chunk } = await getChunkInfo(currentFile.file, i, chunkSize)
const chunkFR = await new FileReader()
await chunkFR.readAsBinaryString(chunk)
await chunkFR.addEventListener('load', async e => {
const chunkBlob = e.target.result
const chunkMD5 = md5(chunkBlob)
await uploadChunk(renwuId, currentFile, { chunkMD5, chunk, currentChunk: i, chunkCount })
}, false)
}
})
}
// 更新进度
const progressFun = () => {
progressNum = Math.ceil(successAllCount / AllChunk * 100)
progress(progressNum)
}
// 对分片已经处理完毕的文件进行上传
const uploadFile = async(renwuId, currentFile, chunkCount) => {
await preview({ // 合并文件
method: 'post',
url: fileUrl,
params: {
renwuId: renwuId,
fileName: currentFile.name,
chunkCount: chunkCount,
type: type
}
}).then(() => {
successAllCount++
progressFun()
success()
}).catch((e) => {
error && error(e)
})
}
const uploadChunk = async(renwuId, currentFile, chunkInfo) => {
const fd = await new FormData()
fd.append('file', await chunkInfo.chunk)
fd.append('fileName', await renwuId)
fd.append('chunkIndex', chunkInfo.currentChunk)
fd.append('chunkCount', chunkInfo.chunkCount)
fd.append('type', type)
await preview({
method: 'post',
url: chunkUrl,
data: await fd
}).then(async() => {
progressFun()
// 当总数大于等于分片个数的时候
if (await (successAllCount < chunkInfo.chunkCount - 1)) {
await (successAllCount++)
} else {
// 当总数大于等于分片个数的时候
if (await (successAllCount >= chunkInfo.chunkCount - 1)) {
await uploadFile(renwuId, currentFile, chunkInfo.chunkCount)
}
}
}).catch((e) => {
error && error(e)
})
}
readFileMD5(files) // 开始执行代码
}