import {
|
fileToUrl,
|
getFileName
|
} from 'uni-platform/helpers/file'
|
/**
|
* 下载任务
|
*/
|
class DownloadTask {
|
_xhr
|
_callbacks = []
|
constructor (xhr) {
|
this._xhr = xhr
|
}
|
|
/**
|
* 监听下载进度
|
* @param {Function} 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 () {
|
if (this._xhr) {
|
this._xhr.abort()
|
delete this._xhr
|
}
|
}
|
}
|
/**
|
* 下载文件
|
* @param {*} param0
|
* @param {string} callbackId
|
* @return {DownloadTask}
|
*/
|
export function downloadFile ({
|
url,
|
header,
|
timeout = (__uniConfig.networkTimeout && __uniConfig.networkTimeout.request) || 60 * 1000
|
}, callbackId) {
|
const {
|
invokeCallbackHandler: invoke
|
} = UniServiceJSBridge
|
var timer
|
var xhr = new XMLHttpRequest()
|
var downloadTask = new DownloadTask(xhr)
|
xhr.open('GET', url, true)
|
Object.keys(header).forEach(key => {
|
xhr.setRequestHeader(key, header[key])
|
})
|
xhr.responseType = 'blob'
|
xhr.onload = function () {
|
clearTimeout(timer)
|
const statusCode = xhr.status
|
const blob = this.response
|
let filename
|
// 使用 getResponseHeader 跨域时会出现警告,但相比 getAllResponseHeaders 更方便
|
const contentDisposition = xhr.getResponseHeader('content-disposition')
|
if (contentDisposition) {
|
// 暂时仅解析 filename 不解析 filename*
|
const res = contentDisposition.match(/filename="?(\S+)"?\b/)
|
if (res) {
|
filename = res[1]
|
}
|
}
|
blob.name = filename || getFileName(url)
|
invoke(callbackId, {
|
errMsg: 'downloadFile:ok',
|
statusCode,
|
tempFilePath: fileToUrl(blob)
|
})
|
}
|
xhr.onabort = function () {
|
clearTimeout(timer)
|
invoke(callbackId, {
|
errMsg: 'downloadFile:fail abort'
|
})
|
}
|
xhr.onerror = function () {
|
clearTimeout(timer)
|
invoke(callbackId, {
|
errMsg: 'downloadFile:fail'
|
})
|
}
|
xhr.onprogress = function (event) {
|
downloadTask._callbacks.forEach(callback => {
|
var totalBytesWritten = event.loaded
|
var totalBytesExpectedToWrite = event.total
|
var progress = Math.round(totalBytesWritten / totalBytesExpectedToWrite * 100)
|
callback({
|
progress,
|
totalBytesWritten,
|
totalBytesExpectedToWrite
|
})
|
})
|
}
|
xhr.send()
|
timer = setTimeout(function () {
|
xhr.onprogress = xhr.onload = xhr.onabort = xhr.onerror = null
|
downloadTask.abort()
|
invoke(callbackId, {
|
errMsg: 'downloadFile:fail timeout'
|
})
|
}, timeout)
|
return downloadTask
|
}
|