為什么會漏掉鏈接?
當你在前端 JavaScript 中快速發起多個下載請求時,瀏覽器可能無法同時處理所有請求,導致一些請求被忽略。這通常與瀏覽器的并發連接限制有關,例如 Chrome 可能限制每秒下載 10 個文件。
如何避免漏掉鏈接?
- 引入延遲: 你可以在每次下載請求之間添加約 333 毫秒的延遲,確保請求逐個處理。
- 使用 JSZip: 另一種方法是使用 JSZip 庫將所有文件打包成一個壓縮文件,然后下載這個壓縮文件,這樣只需發起一個下載請求,減少漏掉的風險。
代碼示例
延遲方法:
const urls = [...]; // 文件 URL 數組
const delay = 333; // 約 1/3 秒延遲for (let i = 0; i < urls.length; i++) {const a = document.createElement('a');a.href = urls[i];a.download = true; // 或指定文件名a.style.display = 'none';document.body.appendChild(a);setTimeout(() => {a.click();document.body.removeChild(a);}, i * delay);
}
JSZip 方法:
首先引入 JSZip 庫:
<script src="https://cdn.skypack.dev/jszip@3.10.1"></script>
然后使用以下代碼:
const urls = [...]; // 文件 URL 數組
const zip = new JSZip();async function batchDownload() {for (let url of urls) {const response = await fetch(url);const blob = await response.blob();const filename = url.split('/').pop();zip.file(filename, blob);}const content = await zip.generateAsync({ type: 'blob' });saveAs(content, 'downloads.zip');
}batchDownload();
意外的細節
Firefox 在處理批量下載時可能表現不同,延遲方法可能無效(具體沒有嘗試),建議使用 JSZip 來確保所有文件都被包含。
詳細講解
問題背景
用戶報告在批量下載時,總是會漏掉后面的幾個下載鏈接。這表明在快速發起多個下載請求時,瀏覽器可能無法處理所有請求,導致一些鏈接被忽略。可能的原因為瀏覽器對并發 HTTP 連接的限制,例如 Chrome 可能限制每秒下載 10 個文件(Chrome/Chromium limits the number of download to a maximum of 10 per second)。此外,不同瀏覽器(如 Firefox)可能有不同的行為,增加了復雜性。
解決方案分析
為了解決這個問題,我們考慮了兩種主要方法:引入延遲和使用 JSZip 創建壓縮文件。
方法 1:引入延遲
通過在每次下載請求之間添加延遲,可以逐個處理請求,避免瀏覽器因并發限制而忽略某些請求。研究表明,約 333 毫秒的延遲(約 1/3 秒)在 Chrome 和 Opera 中有效(Stack Overflow: How in JS to download more than 10 files in browser including Firefox)。
- 實現方式: 使用
setTimeout
在循環中為每個下載請求添加延遲。例如:const urls = [...]; // 文件 URL 數組 const delay = 333; // 約 1/3 秒延遲for (let i = 0; i < urls.length; i++) {const a = document.createElement('a');a.href = urls[i];a.download = true; // 或指定文件名a.style.display = 'none';document.body.appendChild(a);setTimeout(() => {a.click();document.body.removeChild(a);}, i * delay); }
- 優點: 簡單直接,適用于大多數瀏覽器,特別是在 Chrome 和 Opera 中。
- 局限性: 在 Firefox 中可能無效,具體表現因瀏覽器版本和配置而異。
方法 2:使用 JSZip 創建壓縮文件
另一種方法是使用 JSZip 庫將所有文件打包成一個壓縮文件,然后下載這個壓縮文件。這樣只需發起一個下載請求,徹底避免了并發請求的問題。JSZip 是一個 JavaScript 庫,允許在瀏覽器中創建、讀取和編輯 .zip 文件(JSZip Documentation)。
- 實現方式:
首先引入 JSZip 庫:
然后使用以下代碼:<script src="https://cdn.skypack.dev/jszip@3.10.1"></script>
const urls = [...]; // 文件 URL 數組 const zip = new JSZip();async function batchDownload() {for (let url of urls) {const response = await fetch(url);const blob = await response.blob();const filename = url.split('/').pop();zip.file(filename, blob);}const content = await zip.generateAsync({ type: 'blob' });saveAs(content, 'downloads.zip'); }batchDownload();
- 優點: 提供跨瀏覽器一致性,特別是在 Firefox 中表現更好(Stack Overflow: How in JS to download more than 10 files in browser including Firefox)。用戶只需下載一個文件,體驗更佳。
- 局限性: 需要先通過 AJAX 加載所有文件,可能對大文件造成內存壓力,且需要確保文件可通過 AJAX 訪問(同域或配置 CORS)。
瀏覽器差異與注意事項
- Chrome 和 Opera: 通常限制每秒 10 個下載,延遲方法有效(Chrome/Chromium limits the number of download to a maximum of 10 per second)。
- Firefox: 延遲方法可能無效,建議使用 JSZip。Firefox 對 File System API 的支持有限,可能影響大文件下載(MEGA Help Centre: What are the file size limitations when downloading using my browser?)。
- 并發連接限制: 瀏覽器對每個域的并發連接數有限制,通常為 4-6 個(Stack Overflow: max number of concurrent file downloads in a browser?),這可能導致快速發起的請求被隊列化或忽略。
性能與用戶體驗考慮
- 延遲方法: 適合文件數量不多且用戶愿意等待的情況。延遲過長可能影響用戶體驗,建議從 333 毫秒開始測試。
- JSZip 方法: 適合文件數量多或跨瀏覽器兼容性要求高的場景。但對于大文件,內存使用可能成為瓶頸,需注意瀏覽器內存限制(Stack Overflow: Is there any limit to filesize while downloading through browser over http)。
對比表
方法 | 適用場景 | 優點 | 局限性 |
---|---|---|---|
引入延遲 | Chrome、Opera,文件數量少 | 簡單直接,易于實現 | Firefox 可能無效,延遲可能影響體驗 |
使用 JSZip | 跨瀏覽器,文件數量多 | 單一下載請求,體驗更好 | 需要 AJAX 訪問,內存占用可能高 |
結論與建議
引入延遲是解決批量下載漏掉鏈接的直接方法,建議從 333 毫秒開始測試,適用于 Chrome 和 Opera。對于 Firefox 或需要更高可靠性的場景,推薦使用 JSZip 創建壓縮文件,確保所有文件被包含。用戶應根據文件大小、數量和瀏覽器環境選擇合適的方法。
關鍵引用
- Chrome/Chromium limits the number of download to a maximum of 10 per second
- [Stack Overflow: How can I let a user download multiple files when a button is clicked?](https://stackoverflow.com/questions/18451856/how-can-i-let-a-user-download-multiple-files when-a-button-is-clicked)
- Stack Overflow: How in JS to download more than 10 files in browser including Firefox
- JSZip Documentation
- MEGA Help Centre: What are the file size limitations when downloading using my browser?
- Stack Overflow: max number of concurrent file downloads in a browser?
- Stack Overflow: Is there any limit to filesize while downloading through browser over http