JS前端解壓zip的方法和技巧分享
業(yè)務(wù)中有時候需要獲取某個 zip
壓縮包內(nèi)的文件內(nèi)容展示到前端,在 zip
包體積不是那么大的時候(幾MB、十幾MB甚至幾十MB)并且不涉及壓縮包解密的時候,可以考慮純前端方案。
前端使用Jszip解壓zip
安裝依賴: npm i jszip
請求 zip
文件并轉(zhuǎn)為 Blob
:
const blob = await fetch(url).then((res) => res.blob());
使用 jszip
解壓 Blob
:
const zip = new JSZip() const zipData = await zip.loadAsync(zipBlob)
這時候你會得到一個含有 files
列表數(shù)據(jù)的 zipData
, 這個 files
就是壓縮包中的文件列表,這時候的處理就有意思了,下面慢慢說。
如果你的壓縮包里面不止一個文件怎么獲取
基于上一步,我們拿到了 files
文件列表,這時候如果我們的壓縮包里面有很多文件我們怎么全部都拿到呢?我們就需要遞歸這個列表了:
async function extractNestedZip(zipBlob: Blob) { const zip = new JSZip() const zipData = await zip.loadAsync(zipBlob) const extractedFiles: { name: string, data: unkown }[] = [] // 遍歷 ZIP 文件中的所有文件 for (const [name, file] of Object.entries(zipData.files)) { extractedFiles.push({name, file}) } return extractedFiles }
但是事情往往沒有這么簡單,比如壓縮包里面還有壓縮包怎么辦呢?
嵌套壓縮改咋處理
改良 extractNestedZip
方法:
async function extractNestedZip(zipBlob: Blob) { const zip = new JSZip() const zipData = await zip.loadAsync(zipBlob) const extractedFiles: { name: string, data: unkown }[] = [] // 遍歷 ZIP 文件中的所有文件 for (const [name, file] of Object.entries(zipData.files)) { if (name.endsWith('.zip') { // 如果是嵌套的壓縮包就繼續(xù)解壓 const nestedZipBlob = await file.async('blob') const nestedFiles = await extractNestedZip(nestedZipBlob) extractedFiles.push(...nestedFiles) } else { extractedFiles.push({name, file}) } } return extractedFiles }
我們現(xiàn)在解決了嵌套的問題。如果壓縮包中有文件夾該怎么處理呢?嘗試過你會發(fā)現(xiàn)如果是文件夾,在 files
中對應(yīng)的數(shù)據(jù)就是空的,所以我們應(yīng)該過濾這種情況:
壓縮包中的文件夾要過濾
async function extractNestedZip(zipBlob: Blob) { const zip = new JSZip() const zipData = await zip.loadAsync(zipBlob) const extractedFiles: { name: string, data: unkown }[] = [] // 遍歷 ZIP 文件中的所有文件 for (const [name, file] of Object.entries(zipData.files)) { if (name.endsWith('.zip') { // 如果是嵌套的壓縮包就繼續(xù)解壓 const nestedZipBlob = await file.async('blob') const nestedFiles = await extractNestedZip(nestedZipBlob) extractedFiles.push(...nestedFiles) } else if (!name.endsWith('/')) { // 我們可以通過判斷文件名是否以/結(jié)尾來判斷這一項是否是文件夾 extractedFiles.push({name, file}) } } return extractedFiles }
現(xiàn)在看了好像一切都沒問題了,但是我們最終的文件怎么讀到呢?
文本文件和二進制文件要分別處理
如果壓縮包中只包含文本類的文件,比如 .json
,.log
之類的,就可以簡單的用 file.async('text')
來獲取文件內(nèi)容,但是如果包含 .mp3
,.png
就要注意了,我們接下來優(yōu)化這些情況:
async function extractNestedZip(zipBlob: Blob) { const zip = new JSZip() const zipData = await zip.loadAsync(zipBlob) const extractedFiles: { name: string, data: string | Blob }[] = [] // 遍歷 ZIP 文件中的所有文件 for (const [name, file] of Object.entries(zipData.files)) { if (name.endsWith('.zip')) { // 如果文件是嵌套的 ZIP 文件,則遞歸解壓 const nestedZipBlob = await file.async('blob') const nestedFiles: { name: string, data: string | Blob }[] = await extractNestedZip(nestedZipBlob) extractedFiles.push(...nestedFiles) } else { // 如果文件不是 ZIP 文件,則處理 if (name.endsWith('.jpeg') || name.endsWith('.png') || name.endsWith('.mp3') || name.endsWith('.mp4')) { const blob = await file.async('blob') extractedFiles.push({ name, data: blob }) } else if (!name.endsWith('/')) { // 過濾掉文件夾 const fileData = await file.async('text') extractedFiles.push({ name, data: fileData }) } } } return extractedFiles }
我們這里舉了些例子,就是判斷文件名以什么結(jié)尾,如果是常見的媒體格式,就轉(zhuǎn)為 Blob
,不然就轉(zhuǎn)為字符串。這個方案就可以處理壓縮包中不同格式的問題,最終我們就拿到了一個 name
是表示壓縮包中文件名稱,data
是對應(yīng)文件內(nèi)容的列表了。
總結(jié)
在業(yè)務(wù)中需要前端場景解壓壓縮包是比較少見的,但是如果有這類的場景我們就可以借助于 jszip
來做。這次分享的主要是拿到文件之后如何全部拿到壓縮包的所有內(nèi)容的技巧,大家如果有別的問題,歡迎評論區(qū)溝通。
以上就是JS前端解壓zip的方法和技巧分享的詳細內(nèi)容,更多關(guān)于JS前端解壓zip的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
工作中比較實用的JavaScript驗證和數(shù)據(jù)處理的干貨(經(jīng)典)
工作中比較實用的JavaScript驗證和數(shù)據(jù)處理知識經(jīng)常會用到,下面小編通過查閱相關(guān)資料及日常記錄的知識分享到腳本之家平臺,供大家參考2016-08-08JS基于面向?qū)ο髮崿F(xiàn)的多個倒計時器功能示例
這篇文章主要介紹了JS基于面向?qū)ο髮崿F(xiàn)的多個倒計時器功能,結(jié)合實例形式分析了javascript面向?qū)ο蠹皶r間操作相關(guān)技巧,需要的朋友可以參考下2017-02-02使用BroadcastChannel進行跨窗口通信的實例詳解
BroadcastChannel 提供了一種簡單而有效的方式來實現(xiàn)同一瀏覽器環(huán)境下不同頁面或腳本之間的通信,對于需要跨窗口、標(biāo)簽頁或 iframe 同步數(shù)據(jù)的應(yīng)用場景,它是一種非常便捷的解決方案,本文介紹了如何使用 BroadcastChannel 進行跨窗口通信,需要的朋友可以參考下2024-08-08滾動條響應(yīng)鼠標(biāo)滑輪事件實現(xiàn)上下滾動的js代碼
javascript實現(xiàn)滾動條響應(yīng)鼠標(biāo)滑輪的實現(xiàn)上下滾動,示例代碼如下2014-06-06