// 如果上传错误,获取报错信息
function getError(action, option, xhr) {
let msg
if (sponse) {
msg = `${ || sponse}`
} else if (sponseText) {
msg = `${sponseText}`
} else {
msg = `fail to post ${action} ${xhr.status}`
}
const err = new Error(msg)
err.status = xhr.status
err.url = action
return err
}
// 上传成功完成合并之后,获取服务器返回的信息
function getBody(xhr) {
const text = sponseText || sponse
if (!text) {
return text
}
try {
return JSON.parse(text)
} catch (e) {
return text
}
}
// 分⽚上传的⾃定义请求,以下请求会覆盖element的默认上传⾏为
export default function upload(option) {
if (typeof XMLHttpRequest === 'undefined') {
return
}
const spark = new SparkMD5.ArrayBuffer()// md5的ArrayBuffer加密类
const fileReader = new FileReader()// ⽂件读取类
const action = option.action // ⽂件上传上传路径
const chunkSize = 1024 * 1024 * 30 // 单个分⽚⼤⼩
let md5 = ''// ⽂件的唯⼀标识
const optionFile = option.file // 需要分⽚的⽂件
let fileChunkedList = [] // ⽂件分⽚完成之后的数组
const percentage = [] // ⽂件上传进度的数组,单项就是⼀个分⽚的进度
// ⽂件开始分⽚,push到fileChunkedList数组中,并⽤第⼀个分⽚去计算⽂件的md5 for (let i = 0; i < optionFile.size; i = i + chunkSize) {
const tmp = optionFile.slice(i, Math.min((i + chunkSize), optionFile.size))
if (i === 0) {
}
fileChunkedList.push(tmp)
}
// 在⽂件读取完毕之后,开始计算⽂件md5,作为⽂件唯⼀标识
spark.append(sult)
md5 = d() + new Date().getTime()
console.log('⽂件md5为--------', md5)
// 将fileChunkedList转成FormData对象,并加⼊上传时需要的数据
fileChunkedList = fileChunkedList.map((item, index) => {
const formData = new FormData()
if (option.data) {
// 额外加⼊外⾯传⼊的data数据
Object.keys(option.data).forEach(key => {
formData.append(key, option.data[key])
})
// 这些字段看后端需要哪些,就传哪些,也可以⾃⼰追加额外参数
formData.append(option.filename, item, option.file.name)// ⽂件
formData.append('chunkNumber', index + 1)// 当前⽂件块
formData.append('chunkSize', chunkSize)// 单个分块⼤⼩
formData.append('currentChunkSize', item.size)// 当前分块⼤⼩
formData.append('totalSize', optionFile.size)// ⽂件总⼤⼩
formData.append('identifier', md5)// ⽂件标识
formData.append('filename', option.file.name)// ⽂件名
formData.append('totalChunks', fileChunkedList.length)// 总块数
}
return { formData: formData, index: index }
})
// 更新上传进度条百分⽐的⽅法
const updataPercentage = (e) => {
let loaded = 0// 当前已经上传⽂件的总⼤⼩
percentage.forEach(item => {
loaded += item
})
e.percent = loaded / optionFile.size * 100
}
// 创建队列上传任务,limit是上传并发数
function sendRequest(chunks, limit = 3) {
return new Promise((resolve, reject) => {
const len = chunks.length
let counter = 0
let isStop = false
const start = async() => {
if (isStop) {
return
}
const item = chunks.shift()
console.log()
if (item) {js合并两个数组
const xhr = new XMLHttpRequest()
const index = item.index
// 分⽚上传失败回调
isStop = true
reject(e)
}
// 分⽚上传成功回调
if (xhr.status < 200 || xhr.status >= 300) {
isStop = true
reject(getError(action, option, xhr))
}
if (counter === len - 1) {
// 最后⼀个上传完成
resolve()
} else {
counter++
start()
}
}
// 分⽚上传中回调
if (xhr.upload) {
progress = function progress(e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100
}
percentage[index] = e.loaded
console.log(index)
updataPercentage(e)
}
}
xhr.open('post', action, true)
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true
}
const headers = option.headers || {}
for (const item in headers) {
if (headers.hasOwnProperty(item) && headers[item] !== null) {
xhr.setRequestHeader(item, headers[item])
}
}
// ⽂件开始上传
xhr.send(item.formData)
//这⾥是把所有分⽚上传的xhr存到全局中,如果⽤户⼿动取消上传,或者上传出现错误,则要调⽤xhr.abort()把store中所有xhr的停⽌,不然⽂件还会继续上传
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论