中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何下載文件并使用Javascript將其壓縮在瀏覽器中

發布時間:2021-09-30 15:56:08 來源:億速云 閱讀:159 作者:柒染 欄目:web開發

如何下載文件并使用Javascript將其壓縮在瀏覽器中,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

與其生成zip文件并從您的服務器進行傳輸,不如下載數據并將其壓縮在瀏覽器中呢?

我最近從事一個副項目,該項目可根據用戶的請求生成報告。對于每個請求,我們的后端將生成一個報告,將其上傳到Amazon  S3存儲,然后將其URL返回給客戶端。由于生成報告需要一些時間,因此將存儲輸出文件,并且服務器將通過請求參數來緩存其URL。如果用戶訂購相同的商品,則后端將返回現有文件的URL。

幾天前,我有一個新要求,我需要下載一個包含數百個報告的zip文件,而不是單個文件。我想到的第一個解決方案是:

  • 在服務器上準備壓縮文件

  • 上傳到Amazon S3存儲

  • 給客戶端提供下載URL

但是此解決方案有一些缺點:

  • 生成zip文件的邏輯非常復雜。我需要考慮為每個請求生成所有文件,或者在重用現有文件和生成新文件之間進行組合。兩種方法似乎都很復雜。他們將花費一些時間來處理,并且稍后需要大量的編碼,測試和維護。

  • 它無法利用我已經構建的功能。盡管zip文件是不同的報告集,但很可能大多數單個報告都是由較早的請求生成的。因此,雖然zip文件本身不太可能可重用,但單個文件卻可以重用。使用上述方法,我需要一直重做整個過程,這并不是很有效。

  • 生成一個zip文件需要很長時間。由于我的后端是一個單線程進程,因此此操作可能會阻止其他請求一段時間,并且在此期間可能會超時。

  • 在客戶端跟蹤流程非常困難,我喜歡在網站上放置進度欄。如果一切都在后端處理,我需要找到其他方法向前端報告狀態。這并不容易。

  • 我想節省基礎設施的成本。如果我們可以將一些計算轉移到前端并降低基礎架構的成本,那就太好了。我的客戶不介意他們再等幾秒鐘,還是在筆記本電腦上花費額外的MB  RAM。

我想出的最終解決方案是:將所有文件下載到瀏覽器中,然后將其壓縮。在這篇文章中,我將介紹如何做。

免責聲明:在這篇文章中,我假設你已經具有有關Javascript和Promise的基本知識。如果你沒有,我建議你先了解他們,然后再回到這里:)

下載單個文件

在應用新解決方案之前,我的系統允許下載一個報告文件。有很多方法可以做到這一點,后端可以直接通過HTTP請求響應原始文件的內容,也可以將文件上傳到另一個存儲設備并返回文件URL。我選擇第二種方法,因為我想緩存所有生成的文件。

一旦有了文件URL,在客戶端上的工作就非常簡單:在新選項卡中打開此URL。瀏覽器將完成剩下的工作以下載文件。

const downloadViaBrowser = url => {     window.open(url, ‘_blank’); }

下載多個文件并存儲在內存中

當下載和壓縮多個文件時,我們不能再使用上面的簡單方法。

  • 如果一個JS腳本試圖同時打開許多鏈接,瀏覽器會懷疑它是否是一個安全威脅,并警告用戶阻止這些行為。雖然用戶可以確認繼續,但這不是一個好的體驗

  • 你無法控制下載的文件,瀏覽器管理文件內容和位置

解決此問題的另一種方法是使用 fetch  來下載文件并將數據作為Blob存儲在內存中。然后,我們可以將其寫入文件或將這些Blob數據合并為zip文件。

const download = url => {   return fetch(url).then(resp => resp.blob()); };

這個函數返回一個被解析為blob的promise。我們可以結合 Promise.all() 來下載多個文件。Promise.all()  將一次性完成所有的promise,如果所有的子promise都被解析,或者其中一個承諾出現錯誤,則進行解析。

const downloadMany = urls => {   return Promise.all(urls.map(url => download(url)) }

按X文件組下載

但是,如果我們需要一次下載大量文件怎么辦?假設有1000個文件?使用 Promise.all() 可能不再是一個好主意,你的代碼將一次發送一千個請求。  這種方法有很多問題:

  • 操作系統和瀏覽器支持的并發連接數是有限的。因此,瀏覽器一次只能處理幾個請求。其他請求放入隊列,并且超時計數。結果是,你的大多數請求在發送之前都會超時。

  • 一次發送大量請求也會使后端過載

我考慮過的解決方案是將文件分成多個組。假設我有1000個文件可供下載。而不是通過 Promise.all()  立即開始一次下載所有文件,我將每次下載5個文件。在完成這5個之后,我將開始另一個包,我總共會下載250個包。

要實現這個功能,我們可以做一個自定義邏輯。或者我建議一個更簡單的方法,就是利用第三方庫bluebirdjs。該庫實現了許多有用的Promise函數。在這個用例中,我將使用  Promise.map()。注意這里的Promise現在是庫提供的自定義Promise,而不是內置的Promise。

import Promise from 'bluebird'; const downloadByGroup = (urls, files_per_group=5) => {   return Promise.map(     urls,      async url => {       return await download(url);     },     {concurrency: files_per_group}   ); }

通過上面的實現,該函數將接收一個URL數組并開始下載所有URL,每次都具有最大  files_per_group。該函數返回一個Promise,它將在下載所有URL時解析,并在其中任何一個失敗時拒絕。

創建zip文件

現在我已經把所有的內容都下載到內存中了。正如我上面提到的,下載的內容被存儲為Blob。下一步是使用這些Blob數據創建一個壓縮文件。

import JsZip from 'jszip'; import FileSaver from 'file-saver'; const exportZip = blobs => {   const zip = JsZip();   blobs.forEach((blob, i) => {     zip.file(`file-${i}.csv`, blob);   });   zip.generateAsync({type: 'blob'}).then(zipFile => {     const currentDate = new Date().getTime();     const fileName = `combined-${currentDate}.zip`;     return FileSaver.saveAs(zipFile, fileName);   }); }

最終代碼

讓我們在這里完成我為此完成的所有代碼。

import Promise from 'bluebird'; import JsZip from 'jszip'; import FileSaver from 'file-saver'; const download = url => {   return fetch(url).then(resp => resp.blob()); }; const downloadByGroup = (urls, files_per_group=5) => {   return Promise.map(     urls,      async url => {       return await download(url);     },     {concurrency: files_per_group}   ); } const exportZip = blobs => {   const zip = JsZip();   blobs.forEach((blob, i) => {     zip.file(`file-${i}.csv`, blob);   });   zip.generateAsync({type: 'blob'}).then(zipFile => {     const currentDate = new Date().getTime();     const fileName = `combined-${currentDate}.zip`;     return FileSaver.saveAs(zipFile, fileName);   }); } const downloadAndZip = urls => {   return downloadByGroup(urls, 5).then(exportZip); }

總結

利用客戶端的功能有時對于減少后端的工作量和復雜性非常有用。

不要一次發送大量的請求。你會在前端和后端都遇到麻煩。相反,將作品分成小塊。

介紹一些第三方庫bluebird,jszip和file-saver。他們為我工作得很好,也可能對您有幫助。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

惠东县| 酒泉市| 靖江市| 石林| 陕西省| 工布江达县| 青铜峡市| 建湖县| 安泽县| 盐源县| 赣榆县| 成都市| 磐安县| 大竹县| 康保县| 鄱阳县| 自治县| 潜江市| 毕节市| 弥勒县| 大埔区| 汉沽区| 嘉定区| 栖霞市| 东宁县| 靖宇县| 阿拉善左旗| 元江| 内丘县| 城市| 重庆市| 安阳县| 长汀县| 安塞县| 余干县| 六安市| 台中市| 云南省| 百色市| 黄浦区| 扎兰屯市|