import {
|
urlToFile,
|
blobToFile
|
} from 'uni-platform/helpers/file'
|
/**
|
* 上传任务
|
*/
|
class UploadTask {
|
_xhr
|
_isAbort
|
_callbacks = []
|
constructor (xhr, callbackId) {
|
this._xhr = xhr
|
this._callbackId = callbackId
|
}
|
|
/**
|
* 监听上传进度
|
* @param callback 回调
|
*/
|
onProgressUpdate (callback) {
|
if (typeof callback !== 'function') {
|
return
|
}
|
this._callbacks.push(callback)
|
}
|
|
offProgressUpdate (callback) {
|
const index = this._callbacks.indexOf(callback)
|
if (index >= 0) {
|
this._callbacks.splice(index, 1)
|
}
|
}
|
|
/**
|
* 中断上传任务
|
*/
|
abort () {
|
this._isAbort = true
|
if (this._xhr) {
|
this._xhr.abort()
|
delete this._xhr
|
}
|
}
|
}
|
/**
|
* 上传文件
|
* @param {*} param0
|
* @param {*} callbackId
|
* @return {UploadTask}
|
*/
|
export function uploadFile ({
|
url,
|
file,
|
filePath,
|
name,
|
files,
|
header,
|
formData,
|
timeout = (__uniConfig.networkTimeout && __uniConfig.networkTimeout.uploadFile) || 60 * 1000
|
}, callbackId) {
|
const {
|
invokeCallbackHandler: invoke
|
} = UniServiceJSBridge
|
var uploadTask = new UploadTask(null, callbackId)
|
if (!Array.isArray(files) || !files.length) {
|
files = [{
|
name,
|
file,
|
uri: filePath
|
}]
|
}
|
function upload (realFiles) {
|
var xhr = new XMLHttpRequest()
|
var form = new FormData()
|
var timer
|
Object.keys(formData).forEach(key => {
|
form.append(key, formData[key])
|
})
|
Object.values(files).forEach(({ name }, index) => {
|
const file = realFiles[index]
|
form.append(name || 'file', file, file.name || `file-${Date.now()}`)
|
})
|
xhr.open('POST', url)
|
Object.keys(header).forEach(key => {
|
xhr.setRequestHeader(key, header[key])
|
})
|
xhr.upload.onprogress = function (event) {
|
uploadTask._callbacks.forEach(callback => {
|
var totalBytesSent = event.loaded
|
var totalBytesExpectedToSend = event.total
|
var progress = Math.round(totalBytesSent / totalBytesExpectedToSend * 100)
|
callback({
|
progress,
|
totalBytesSent,
|
totalBytesExpectedToSend
|
})
|
})
|
}
|
xhr.onerror = function () {
|
clearTimeout(timer)
|
invoke(callbackId, {
|
errMsg: 'uploadFile:fail'
|
})
|
}
|
xhr.onabort = function () {
|
clearTimeout(timer)
|
invoke(callbackId, {
|
errMsg: 'uploadFile:fail abort'
|
})
|
}
|
xhr.onload = function () {
|
clearTimeout(timer)
|
const statusCode = xhr.status
|
invoke(callbackId, {
|
errMsg: 'uploadFile:ok',
|
statusCode,
|
data: xhr.responseText || xhr.response
|
})
|
}
|
if (!uploadTask._isAbort) {
|
timer = setTimeout(function () {
|
xhr.upload.onprogress = xhr.onload = xhr.onabort = xhr.onerror = null
|
uploadTask.abort()
|
invoke(callbackId, {
|
errMsg: 'uploadFile:fail timeout'
|
})
|
}, timeout)
|
xhr.send(form)
|
uploadTask._xhr = xhr
|
} else {
|
invoke(callbackId, {
|
errMsg: 'uploadFile:fail abort'
|
})
|
}
|
}
|
|
Promise
|
.all(files.map(({ file, uri }) => file instanceof Blob ? Promise.resolve(blobToFile(file)) : urlToFile(uri)))
|
.then(upload)
|
.catch(() => {
|
setTimeout(() => {
|
invoke(callbackId, {
|
errMsg: 'uploadFile:fail file error'
|
})
|
}, 0)
|
})
|
|
return uploadTask
|
}
|