uni-app 支付宝云内置存储的响应Headers里没有content-length

发布于 1周前 作者 ionicwang 来自 Uni-App

uni-app 支付宝云内置存储的响应Headers里没有content-length

操作步骤:

const downloadTask = uni.downloadFile({ url: data.download_url.default_android, header: { accept: ‘text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/;q=0.8,application/signed-exchange;v=b3;q=0.7’, ‘content-type’: ‘application/octet-stream’, }, success(res) { console.log(res.tempFilePath) }, fail(e) { console.log(e) } }) downloadTask.onProgressUpdate(res => { console.log('进度: ', res.progress) console.log('具体: ', Number((res.totalBytesWritten / 1024 / 1024).toFixed(2)), Number((res.totalBytesExpectedToWrite / 1024 / 1024).toFixed(2))) if (res.progress > 20) { downloadTask.abort() } })


## 预期结果:

downloadTask.onProgressUpdate能生效,实时获取下载进度

实际结果:

downloadTask.onProgressUpdate未生效,里面的代码未执行


## bug描述:

支付宝云内置存储的响应Headers里没有content-length,这就导致uni.downloadFile下载的时候,downloadTask.onProgressUpdate无效,无法获取下载文件的进度,用户在更新app的时候体验极差

2 回复

正在排查,问题已反馈支付宝云


在处理uni-app与支付宝云内置存储的集成时,如果遇到响应Headers里没有content-length的问题,这通常是因为后端服务或云存储服务在返回数据时未明确设置该头部信息。虽然content-length对于某些HTTP客户端来说是必要的,但现代HTTP/2协议通常不再严格要求它,因为流控制机制已经内置于协议中。不过,如果你确实需要处理这个问题,尤其是在需要精确控制数据接收的情况下,可以考虑以下几种方法。

方法一:使用Range请求

如果你只是想验证数据完整性或分段下载,可以尝试使用Range请求头来获取数据的特定部分。这样,你可以通过多次请求来手动计算出总内容长度。

// 示例:使用uni-app发起带有Range头的请求
uni.request({
    url: 'https://your-alipay-cloud-storage-url/file',
    method: 'GET',
    header: {
        'Range': 'bytes=0-99' // 请求文件的前100个字节
    },
    success: (res) => {
        console.log(res.data); // 处理返回的数据片段
        // 可以通过多次请求不同范围的数据来拼接完整文件
    },
    fail: (err) => {
        console.error(err);
    }
});

方法二:处理Transfer-Encoding: chunked

如果服务器返回的是Transfer-Encoding: chunked,这意味着数据是以一系列块的形式发送的,每个块都有自己的大小标记。在客户端,你需要处理这种流式数据,而不是依赖于content-length

// 示例:处理chunked编码的响应数据
uni.request({
    url: 'https://your-alipay-cloud-storage-url/stream',
    method: 'GET',
    responseType: 'arraybuffer', // 假设你需要二进制数据
    success: (res) => {
        let chunks = [];
        res.onDataChunk = (chunk) => {
            chunks.push(chunk);
        };
        res.onLoaded = (event) => {
            if (event.complete) {
                let fullData = new Uint8Array(chunks.reduce((acc, chunk) => acc.concat(chunk), []));
                // 处理完整的二进制数据
            }
        };
    },
    fail: (err) => {
        console.error(err);
    }
});

注意,上述代码是概念性的示例,实际实现可能需要根据uni-app的具体API和支付宝云存储的响应格式进行调整。在处理流式数据时,确保正确管理内存和资源,避免内存泄漏或请求超时等问题。

回到顶部