如何在浏览器中使用Worker线程显示下载进度?

新手上路,请多包涵

使用worker线程异步下载项目中的附件,选择100个,下载成100个文件的需求。(目前最多同时下载10个)在modelAndView跳转的对应的jsp中,然后new worker请求下载附件,在worker使用XMLHttpRequest请求下载。然后再worker的监听事件中使用a标签下载附件。
这存在一个问题,只会在下载完成时候的时候浏览器弹出附件下载框,不显示下载进度信息。
怎么显示下载进度信息?示例代码如下:
worker.onmessage = function(){
let blobUrl = new Blob([res.data], {type: 'application/zip'})
let a = document.createElement('a');
let url = window.URL.createObjectURL(blobUrl);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}

希望和在浏览器中出现下载进度。

阅读 527
avatarAI BotBETA

要在浏览器中使用 Web Worker 线程显示下载进度,你需要做几件事情:

  1. 修改 Worker 以返回下载进度:你需要让 Worker 定期发送消息回主线程,报告下载的进度。
  2. 在主线程中更新进度:根据 Worker 发送的进度信息,更新 UI 显示下载进度。

下面是一个修改后的示例,展示如何显示下载进度。这个示例包括在主线程和 Worker 线程之间的通信。

主线程代码(JSP 页面中的 JavaScript)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Download with Progress</title>
</head>
<body>
    <div id="progress-container">
        <div id="progress-bar" style="width: 0%; background-color: green; text-align: center; color: white; padding: 1px;">0%</div>
    </div>

    <script>
        const worker = new Worker('downloadWorker.js');

        // 发送下载任务给 Worker
        const urls = [/* 这里是100个附件的URL数组 */];
        const batchSize = 10;  // 同时下载的最大数量
        let currentIndex = 0;

        function startDownloads() {
            for (let i = 0; i < batchSize && currentIndex < urls.length; i++) {
                worker.postMessage({ url: urls[currentIndex], index: currentIndex });
                currentIndex++;
            }
        }

        worker.onmessage = function(event) {
            const { index, progress, data, fileName } = event.data;
            if (progress !== undefined) {
                const totalDownloads = urls.length;
                const overallProgress = ((index + 1) * batchSize + progress) / (totalDownloads * 100);
                const progressBar = document.getElementById('progress-bar');
                progressBar.style.width = `${Math.min(overallProgress * 100, 100)}%`;
                progressBar.textContent = `${Math.min(overallProgress * 100, 100).toFixed(2)}%`;
            } else if (data && fileName) {
                const blobUrl = URL.createObjectURL(new Blob([data], { type: 'application/zip' }));
                const a = document.createElement('a');
                a.href = blobUrl;
                a.download = fileName;
                a.click();
                URL.revokeObjectURL(blobUrl);

                // 如果有更多文件需要下载,继续下载
                if (currentIndex < urls.length) {
                    startDownloads();
                }
            }
        };

        // 开始下载
        startDownloads();
    </script>
</body>
</html>

Worker 线程代码(downloadWorker.js)

self.onmessage = function(event) {
    const { url, index } = event.data;
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';

    xhr.onprogress = function(e) {
        if (e.lengthComputable) {
            const progress = Math.round((e.loaded * 100) / e.total);
            self.postMessage({ index, progress });
        }
    };

    xhr.onload = function() {
        if (xhr.status === 200) {
            self.postMessage({ index, data: xhr.response, fileName: `file_${index}.zip` });
        } else {
            console.error(`Failed to download file ${index}: ${xhr.statusText}`);
        }
    };

    xhr.onerror = function() {
        console.error(`Error downloading file ${index}`);
    };

    xhr.send();
};

解释

  1. 主线程

    • 创建一个进度条容器。
    • 使用 Web Worker 发送下载任务。
    • 监听 Worker 发送的消息,更新进度条。
    • 下载完成后,创建 Blob URL 并模拟点击 <a> 标签下载文件。
    • 如果还有文件需要下载,继续发送下载任务。
  2. Worker 线程

    • 接收下载任务(URL 和索引)。
    • 使用 XMLHttpRequest 发起下载请求。
    • onprogress 事件中,计算并发送下载进度给主线程。
    • onload 事件中,发送下载的数据和文件名给主线程。

这样,你就可以在浏览器中显示下载进度了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏