背景
uniapp开发的安卓app运行时,uni.downloadFile下载文件,偶发性下载失败、没有反应,也不进入complete回调函数,onProgressUpdate也不执行,代码如下
var uploadTask = uni.downloadFile({
url:"",
success:function(res){
//输出res.tempFilePath之类的
},
fail:function(e){
},
complete:function(e){
//不进入
}
})
//进度更新
uploadTask.onProgressUpdate((result) => {
//也不进入
})
同事使用plus api可以成功下载
plus.downloader.createDownload(
url,
{
timeout,
filename: TEMP_PATH + '/download/',
// 需要与其它平台上的表现保持一致,不走重试的逻辑。
retry: 0,
retryInterval: 0,
},
解决
百度相关帖子,发现有的下载失败是因为url中有特殊字符,而我不属于这种情况,好在这个bug能稳定复现,经观察,
失败时服务器端写入的http Response Header如下
Content-Disposition: inline; filename="Some's file name.pdf";
抱着试一试的心态,将filename中特殊字符单引号('),去掉后,成功下载。
后续
带着好奇心,看了下uniapp的源码,
h5版本的源码
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)
resolve({
statusCode,
tempFilePath: fileToUrl(blob),
})
}
xhr.onabort = function () {
clearTimeout(timer)
reject<Partial<DownloadFileFail>>('abort', { errCode: 600003 })
}
xhr.onerror = function () {
clearTimeout(timer)
reject<Partial<DownloadFileFail>>('', { errCode: 602001 })
}
app版本的源码
const downloader = plus.downloader.createDownload(
url,
{
timeout,
filename: TEMP_PATH + '/download/',
// 需要与其它平台上的表现保持一致,不走重试的逻辑。
retry: 0,
retryInterval: 0,
},
(download, statusCode) => {
if (statusCode) {
resolve({
tempFilePath: download.filename!,
statusCode,
})
} else {
reject(`statusCode: ${statusCode}`)
}
}
)
推测
安卓运行,会执行app版本源码?如果是,从app版源码上,看不出来有什么问题,只能推测是上一层uni封装downloadFile时,解析fileName出问题了。