uni-app uni.downloadFile 真机上下载文件超时 time out

发布于 1周前 作者 gougou168 最后一次编辑是 5天前 来自 uni-app

产品分类

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>

操作步骤

  1. 修改tempFileURLs变量中的文件地址(我的文件可能会过期)
  2. 运行程序到真机中
  3. 点击下载按钮
  4. 打开控制台查看log

预期结果

能够正常下载完整的文件

实际结果

10秒后就提示 errno: 5, errMsg: "downloadFile:fail fail:time out"

bug描述

errno: 5, errMsg: "downloadFile:fail fail:time out" 使用微信开发者调试工具的真机模拟是可以下载文件的,不会超时. 但是一旦使用真机预览,查看控制台就可以看到下面截图的报错,代码里的默认timeout10000ms也就是10s,按道理这个是与服务器失去连接后10s后报超时错误,但是通过截图可以看到实际上一直都在下载文件,与服务器连接一直通畅的,但是10s到了后就直接报超时了???

我默认使用的是支付宝云存储中的文件,我也试过别的文件,都是在真机预览10s后报超时。

下载超时报错


4 回复

使用其他文件没事,使用支付宝云存储的文件有这个问题是吗?


都有这个问题

回复 c***@163.com: 那可能是小程序的 bug,可以在开发者社区给小程序反馈一下,说一下模拟器和真机行为不一致

在处理 uni-app 中使用 uni.downloadFile 方法下载文件时遇到超时(time out)问题,通常是由于网络不稳定、服务器响应慢或者文件过大等原因导致的。为了更有效地处理这种情况,你可以在代码中添加超时控制机制,并处理超时后的逻辑。以下是一个使用 PromisesetTimeout 来实现下载文件超时控制的示例代码:

// 定义一个下载文件的函数,包含超时控制
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等),文件保存的具体实现可能有所不同,你可能需要根据平台特性调整保存文件的代码部分。

回到顶部