主要是写了一个大体的思路,需微调整
import Compressor from 'compressorjs'
import {satrtUpload,satrtBinaryUpload,remuseUpload, remuseBinaryUpload} from serviceData
// 转base64或二进制流 blob 二进制文件 tupe base64 和 binary
const blobToBase64 = (blob, type = 'BASE64')=>{
return new Promise((resolve,reject)=>{
try{
const render = new FileReader()
if(type === 'BASE64'){
render.readAsDataURL(Blob)
}else{
render.readAsArrayBuffer(blob)
}
render.onload = (e) =>{
if(type = 'BASE64'){
resolve(e.target.result)
}else{
const binaryArr = new Int8Array(render.result)
resolve(binaryArr)
}
}
} catch(e){
reject(e)
}
})
}
// 文件压缩
const compress = (file) => {
return new Promise((resolve, reject) => {
if (!file) {
return reject(new Error('文件上传失败,请重试'))
}
let quality = 0.6
const fileSize = Number(file.size) || 0
if (fileSize >= 10485760) {
quality = 0.1
} else if (fileSize < 3145728 && fileSize >= 1048576) {
quality = 0.3
} else if (fileSize < 1048576 && fileSize >= 524288) {
quality = 0.8
} else {
quality = 1
}
new Compressor(file, {
quality,
success: async (result) =>{
const base64 = await blobToBase64(result)
const binary = await blobToBase64(result, 'BINARY')
let base64Str = base64
if(base64 && base64.length > 20){
if(base64.indexOf(',') > -1){
base64Str = base64.split(',')[1]
}
resolve({base64,base64Str, binary})
}else{
reject(new Error('图片流为空'))
}
},
error: (err)=>{
reject(err)
}
})
})
}
let base64Data = ''
let binaryData = []
let fileType = ''
let fileSize = ''
// 文件change事件
const fileChange = async (e) =>{
const file = e.target.files[0]
const {base64,binary} = await compress(file)
base64Data = base64
binaryData = binary
fileType = file.type.split('/')[1]
fileSize = file.size
beforeUpload('BINARY')
}
// 分片上传参数
let uploadCount = '' //次数
let uploadId = '' //id
let uploadSize = '' //单次上传大小
let remainIds = []
let uploaded = []
let retryTimes = 0 //重试次数
let allIds = []
// 开始上传
const beforeUpload = async(fileDataType = 'BASE64') =>{
let data = {}
if(fileDataType === 'BASE64'){
data = await satrtUpload({fileSize: base64Data.length})
}else{
data = await satrtBinaryUpload({fileSize,fileType})
}
if(data.type === 1){
// 直接上传
this.$emit('afterUpload',1)
}else if(data.type === 2){
// 分片上传
uploadCount = data.count
uploadId = data.id
uploadSize = data.size
uploadCount = data.count
const temp = []
for(let i = 0; i <uploadCount; i++){
temp.push(i)
}
allIds = temp
initResume([])
}
}
let initResume = async (uploaded) =>{
remainIds = await allIds.filter(item =>{
uploaded.indexOf(item) < 0
})
resumeUpload()
}
// 分片上传
const resumeUpload = async () =>{
if(retryTimes >= 10){
return toast('上传重试达到10次,已取消上传')
}
for(let i = 0; i < remainIds.length; i++){
const no = remainIds[i]
let remuseData = ''
if(fileDataType === 'BASE64'){
remuseData = base64Data.slice(uploadSize * no, uploadSize * (no + 1))
await remuseUpload({no,remuseData})
uploaded.push(no)
}else{
remuseData = binaryData.slice(uploadSize * no, uploadSize * (no + 1))
let form = new FormData()
form.append('no',no)
form.append('uploadId',uploadId)
form.append('remuseData',remuseData)
await remuseBinaryUpload({no,remuseData})
uploaded.push(no)
}
}
let data = {}
if(fileDataType === 'BASE64'){
data = await endUpoad({})
}else{
data = await endBinaryUpoad({uploadId})
}
if(data.remainCount > 0){
// 重试
retryTimes++
uploaded = data.uploaded
await initResume(uploaded)
}else{
// 上传完成
this.$emit('afterUpload',2,uploadId)
}
}