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
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) // 开始执行代码
|
|
}
|
|
|