uni-app uni.downloadFile 真机上下载文件超时 time out
产品分类
uniapp/小程序/微信
开发环境信息
项目 | 详情 |
---|---|
PC开发环境操作系统 | Windows |
操作系统版本号 | win10 22631.4751 |
HBuilderX类型 | 正式 |
HBuilderX版本号 | 4.45 |
第三方开发者工具版本号 | Stable 1.06.2409140 |
基础库版本号 | 3.7.1 |
项目创建方式 | HBuilderX |
示例代码
<template>
<view>
<button @click="main()">下载</button>
</view>
</template>
<script setup lang="ts">
/**
* @desc 函数节流,单位时间内多次执行只执行一次
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发
*/
function throttle(func, wait = 1000, type = 1) {
let previous = 0;
let timeout;
return function () {
let context = this;
let args = arguments;
if (type === 1) {
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
} else if (type === 2) {
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
async function main() {
const tempFileURLs = "填写文件下载地址,起码需要下载超过10s的文件(或者适当调整timeout数值)";
const objPath = `${wx.env.USER_DATA_PATH}/dictionary/`;
const fileName = "dictionary.br";
downloadFile(tempFileURLs, objPath, fileName);
}
function downloadFile(link, objPath, fileName, timeout = 10000) {
return new Promise((resolve, reject) => {
const csvDownloadTask = uni.downloadFile({
url: link, //下载的url
timeout: timeout,
success: (res) => {
if (res.statusCode === 200) {
console.log(`文件${fileName}下载成功`, res);
resolve(res);
} else {
console.error(`文件${fileName}下载失败,code:${res.statusCode}`);
reject(res.statusCode);
}
},
fail(e) {
console.error(`文件${fileName}下载失败:`, e);
reject(e);
}
});
csvDownloadTask.onProgressUpdate(throttle((res) => {
console.log(`${fileName}展示进度obj:`, res);
console.log(`${fileName}下载进度:${res.progress}`);
console.log(`${fileName}已经下载的数据长度${res.totalBytesWritten}`);
console.log(`${fileName}预期需要下载的数据总长度:${res.totalBytesExpectedToWrite}`);
}, 300));
})
}
</script>
操作步骤
- 修改
tempFileURLs
变量中的文件地址(我的文件可能会过期) - 运行程序到真机中
- 点击下载按钮
- 打开控制台查看log
预期结果
能够正常下载完整的文件
实际结果
10秒后就提示 errno: 5, errMsg: "downloadFile:fail fail:time out"
bug描述
errno: 5, errMsg: "downloadFile:fail fail:time out"
使用微信开发者调试工具的真机模拟是可以下载文件的,不会超时.
但是一旦使用真机预览,查看控制台就可以看到下面截图的报错,代码里的默认timeout
是10000ms
也就是10s
,按道理这个是与服务器失去连接后10s
后报超时错误,但是通过截图可以看到实际上一直都在下载文件,与服务器连接一直通畅的,但是10s
到了后就直接报超时了???
我默认使用的是支付宝云存储中的文件,我也试过别的文件,都是在真机预览10s
后报超时。
都有这个问题
回复 c***@163.com: 那可能是小程序的 bug,可以在开发者社区给小程序反馈一下,说一下模拟器和真机行为不一致
在处理 uni-app
中使用 uni.downloadFile
方法下载文件时遇到超时(time out)问题,通常是由于网络不稳定、服务器响应慢或者文件过大等原因导致的。为了更有效地处理这种情况,你可以在代码中添加超时控制机制,并处理超时后的逻辑。以下是一个使用 Promise
和 setTimeout
来实现下载文件超时控制的示例代码:
// 定义一个下载文件的函数,包含超时控制
async function downloadFileWithTimeout(url, filePath, timeout = 10000) { // 默认超时时间为10秒
return new Promise((resolve, reject) => {
// 使用 setTimeout 来设置超时
const timer = setTimeout(() => {
reject(new Error('Download file timeout'));
}, timeout);
uni.downloadFile({
url: url,
success: (res) => {
clearTimeout(timer); // 下载成功,清除超时计时器
const tempFilePath = res.tempFilePath;
// 如果需要,可以将文件保存到指定路径
// 这里的 filePath 是保存文件的路径,但需要注意 uni-app 的文件保存规则
// 例如,在小程序中,你可能需要使用 uni.saveFile 方法
// uni.saveFile({
// tempFilePath: tempFilePath,
// success: (saveRes) => {
// resolve(saveRes.savedFilePath);
// },
// fail: (err) => {
// reject(err);
// }
// });
// 如果只是需要临时文件路径,则直接返回
resolve(tempFilePath);
},
fail: (err) => {
clearTimeout(timer); // 下载失败,清除超时计时器
reject(err);
}
});
});
}
// 使用示例
downloadFileWithTimeout('https://example.com/file.zip', '/path/to/save/file.zip')
.then((filePath) => {
console.log('File downloaded successfully:', filePath);
})
.catch((error) => {
console.error('Failed to download file:', error.message);
});
在上述代码中,downloadFileWithTimeout
函数接收三个参数:文件的 URL、保存文件的路径(注意,这里的路径处理可能因平台而异,具体实现需参考 uni-app
文档),以及可选的超时时间(默认为10秒)。函数返回一个 Promise
,使用 setTimeout
设置一个超时计时器。如果下载成功,则清除计时器并解析 Promise;如果下载失败或超时,则拒绝 Promise 并输出错误信息。
请注意,对于不同平台(如小程序、H5、App等),文件保存的具体实现可能有所不同,你可能需要根据平台特性调整保存文件的代码部分。