自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

ZIP 也能邊下載邊解壓?流式解壓技術(shù)揭秘!

開發(fā) 開發(fā)工具
對(duì)于一個(gè) ZIP 文件,由于標(biāo)準(zhǔn)的解壓方式總是從讀取文件的末尾開始的,因此必須下載完整個(gè) ZIP 解壓后才能訪問。

 ????對(duì)于一個(gè) ZIP 文件,由于標(biāo)準(zhǔn)的解壓方式總是從讀取文件的末尾開始的,因此必須下載完整個(gè) ZIP 解壓后才能訪問。當(dāng)用戶通過網(wǎng)絡(luò)訪問 ZIP 文件時(shí),下載解壓所帶來的耗時(shí)將大大降低用戶體驗(yàn)。那么能不能邊下載邊解壓呢?阿里巴巴文娛技術(shù) 喻遠(yuǎn)將介紹 ZIP 流式解壓的原理和技術(shù)實(shí)現(xiàn)路徑。

打開網(wǎng)絡(luò)上的 ZIP 文件需要幾步?下載,解壓,拿到所有文件。面對(duì)一個(gè) ZIP,能不能「邊下邊播」、「按需下載」?

今年 6 月,優(yōu)酷繪本技術(shù)團(tuán)隊(duì)開發(fā)出新的解壓方式——ZIP 流式解壓技術(shù),并成功應(yīng)用在優(yōu)酷繪本秒開項(xiàng)目中,30M+ 繪本平均加載時(shí)長只需 0.91s,加載耗時(shí)比傳統(tǒng)的解壓方式降低了 88.3%,讓用戶的閱讀體驗(yàn)直線提升。實(shí)際對(duì)比效果如下:

??

??

 

優(yōu)化前

??

[[341409]]

??

 

優(yōu)化后

本文將介紹 ZIP 流式解壓的原理和技術(shù)實(shí)現(xiàn)路徑,希望為大家?guī)韱l(fā),將 ZIP 流式解壓技術(shù)更多的應(yīng)用到業(yè)務(wù)中。

一 什么是ZIP

ZIP 是一種文件格式,定義了如何將多個(gè)文件、數(shù)據(jù)塊組織在一起形成一個(gè)完整的文件。例如我們常見的 .apk,.ipa,.sketch,都是ZIP文件。通常程序是這樣創(chuàng)建 ZIP 文件的:

壓縮單個(gè)文件形成單文件數(shù)據(jù)塊;

在數(shù)據(jù)塊前后添加文件描述信息;

對(duì)每個(gè)待壓縮的文件重復(fù)以上步驟后,拼接所有數(shù)據(jù)形成更大的數(shù)據(jù)塊;

提取所有文件描述信息,生成一份「文件目錄」,附在最后一個(gè)數(shù)據(jù)塊的尾部。

我們將文件前部描述信息稱為 Local File Header,文件后部描述信息稱為 Data Descriptor, 被壓縮的文件本身稱為 File Data,將最后的文件目錄稱為 Central Directory。以上所有合在一起,就是一個(gè)標(biāo)準(zhǔn)的 ZIP 文件。如下圖:

??

??

 

ZIP 文件格式

一個(gè)標(biāo)準(zhǔn)的解壓方式總是從讀取 ZIP 文件末尾開始的,我們以解壓上圖的 File Data 1 為例:

??

??

 

首先在 ZIP 文件末尾找到 Central Directory 數(shù)據(jù)塊;

在 Central Directory 數(shù)據(jù)塊中找到 File Header 1;

從 File Header 1 中讀取 Local File Header 1 的偏移量和 File Data 1 的相關(guān)信息;

根據(jù)偏移量找到 Local File Header 1;

讀取 Local File Header 1;

解密 File Data 1(如果需要);

解壓 File Data 1;

讀取 Data Descriptor 1;

使用 File Header 1 中保存的 CRC-32 做校驗(yàn)步驟 7 中計(jì)算的 CRC-32,以確保解壓后的數(shù)據(jù)完整性。

標(biāo)準(zhǔn)解壓方式存在的不足

可以發(fā)現(xiàn),標(biāo)準(zhǔn)的解壓強(qiáng)依賴尾部的 Central Directory。當(dāng) ZIP 文件存儲(chǔ)在 cdn 上時(shí),哪怕我們只想訪問其中的一個(gè)文件,也必須下載整個(gè) ZIP 解壓后才可訪問。假如 ZIP 文件有 100 MB,但是我們只需要訪問其中的某一個(gè) 10 KB 的文件,那么下載整個(gè) ZIP 將是對(duì)流量的巨大浪費(fèi)。

二 優(yōu)酷技術(shù)方案:ZIP流式解壓

我們的一個(gè)初步的想法是能不能邊下載邊解壓?

要實(shí)現(xiàn)這點(diǎn),首先需要改變解壓方式,使其不能再依賴尾部的 Central Directory。

根據(jù) ZIP 文件格式標(biāo)準(zhǔn)可知,除了 Central Directory,每個(gè) File Data 頭部的 Loca File Header 部分也包含了該文件的相關(guān)信息。

假如 Local File Header 中包含了充分的信息,我們也許可以基于 Local File Header 去解壓文件數(shù)據(jù),其解壓流程就可以變?yōu)椋?/p>

??

??

 

從頭開始,搜索到 Local File Header 1;

讀取 Local File Header 1;

解密 File Data 1(如果需要);

解壓 File Data 1;

讀取 Data Descriptor 1;

CRC32 的校驗(yàn)。

那么 Local File Header 里到底存儲(chǔ)了什么?是否滿足解密解壓所需?

了解 Local File Header

我們根據(jù)文檔對(duì) Local File Header 的描述,畫出其二進(jìn)制文件中的排列:

??

??

 

Local File Header 數(shù)據(jù)結(jié)構(gòu)

其中的關(guān)鍵信息為:

Signature

元數(shù)據(jù)簽名

Compress Method

壓縮算法

Compressed Size

壓縮后文件大小

Uncompressed Size

壓縮前文件大小

CRC-32

文件的循環(huán)冗余校驗(yàn)值

File name

文件名

元數(shù)據(jù)簽名是一個(gè) Magic Number,用來標(biāo)記接下來數(shù)據(jù)是什么內(nèi)容。例如 Local File Header 的簽名是 0x04034b50,用 char 表示也就是 { 'P', 'K', '3', '4' }。當(dāng)讀取到對(duì)應(yīng)數(shù)據(jù)簽名時(shí),則意味著接下來的數(shù)據(jù)結(jié)構(gòu)符合對(duì)應(yīng)元數(shù)據(jù)的定義,需要使用對(duì)應(yīng)規(guī)則解析。

Compress Method 指明數(shù)據(jù)塊用何種算法壓縮,解壓需要使用對(duì)應(yīng)的算法。

Compressed Size 和 UnCompressed Size可以幫助確定文件的結(jié)尾地址和 Data Descriptor 的偏移量。這兩個(gè) Size 也是文件解密時(shí) HMAC 計(jì)算的關(guān)鍵。

有了 Magic Number 作為元數(shù)據(jù)簽名,我們只需要逐字節(jié)遍歷去匹配這個(gè) Number,就可以找到 Loca File Header,而不再需要依賴尾部的定位信息。而且 Local File Header 中存儲(chǔ)的元數(shù)據(jù)足夠我們決定解壓算法、計(jì)算大小、校驗(yàn) CRC-32 了。

還有一個(gè)問題是,解壓縮算法是否支持流式解壓縮?是否有特定的上下文依賴?通過了解壓縮算法的原理[1],我們知道,所有的壓縮算法都是支持從頭部開始流式解壓的。

而下載方面,文件是以從頭到尾連續(xù)的方式下載,這又天然地和和從頭解壓的方式配合,便可以初步實(shí)現(xiàn)邊下邊解!

加密 ZIP 文件的問題

一切都相當(dāng)順利,直到遇到了加密后的 ZIP 文件。加密后的 ZIP 文件的 Local File Header 中的關(guān)鍵信息除了簽名和文件名以外,其他信息都被隱去,需要去 Central Directory 中讀取。

再一次,我們回到了依賴 Central Directory 的狀態(tài)。

在失去如此多關(guān)鍵信息的情況下能否繼續(xù)做到流式解壓?我們需要先挖掘一下 ZIP 的加密方式。

ZIP 的加密方式

ZIP 文件支持多種加密方式,最常見的是 Traditional PKWARE Encryption 和 AES Encryption 。

Traditional PKWARE Encryption 是 ZIP 自定義的一種基于密碼的對(duì)稱加密方式,每個(gè)字節(jié)的加密僅和密碼有關(guān),加密前后的數(shù)據(jù)長度不變。這種不依賴上下文的加密方式可以實(shí)現(xiàn)我們需要的流式解密。

AES 加密采用的是 CTR 模式。CTR 模式將明文分組,并生成一個(gè)計(jì)數(shù)器。使用密鑰對(duì)計(jì)數(shù)器進(jìn)行加密生成二進(jìn)制字節(jié)流。利用這個(gè)字節(jié)流和明文進(jìn)行 XOR 操作進(jìn)行加密。其解密方式也是一樣的。

這種方式也支持流式解密。

??

??

 

兩種常用的加密方式都支持流式解密,那么加解密需要的關(guān)鍵信息,在 Local File Header 中是否有存儲(chǔ)就成了能否流式解密的關(guān)鍵。

流式解密的關(guān)鍵信息

無論是 Traditional PKWARE Encryption 還是 AES Encryption,在解密時(shí)都需要一些除密碼之外的關(guān)鍵信息,例如鹽值,加密算法的強(qiáng)度等。此外,在 AES 加密的 ZIP 文件中, Local File Header 中的 Compress Method 字段被抹去,這樣我們便無法知曉壓縮算法,因此無法解壓。

至此,問題集中為:

  • Local File Header 中是否有足夠的加密所需信息。
  • 加密的 ZIP 文件,是否能在除 Central Directory 以外的位置找到 Compress Method 字段。

Local File Header 中加密相關(guān)的信息

ZIP 格式的設(shè)計(jì)者在設(shè)計(jì) ZIP 文件格式的初期就提供了文件拓展能力,一些額外的拓展數(shù)據(jù)可以存放在 Local File Header 的 Extra Field 中。ZIP AES 加密說明書[2]告訴我們 AES 的相關(guān)信息就存放在這里。其關(guān)鍵信息如下:

Signature

Extra Data 簽名(0x9901)

AES Encryption strength

AES 加密強(qiáng)度(128或192或256)

Actual compress Method

真正的壓縮算法

原來壓縮算法被藏到了 Extra Data 中。那么鹽值被存放在哪里了?答案是存放在 File Data 的頭尾。

??

??

 

綜上,我們找到解密所需的所有關(guān)鍵信息,整個(gè)流式解密解壓的所有技術(shù)點(diǎn)都被我們探索完。剩下的便是按原理實(shí)現(xiàn),以及細(xì)節(jié)的打磨。

三 總結(jié)

說了那么多,流式解壓究竟有什么價(jià)值呢?

由于流式解壓實(shí)現(xiàn)了邊下載邊解壓,將整個(gè)操作的時(shí)長從下載 + 解壓縮變成了約等于純下載的時(shí)長,直接抹掉了解壓的耗時(shí)。在 39.1 MB 大小的 ZIP 包下載解壓測(cè)試中,耗時(shí)從 9.08 秒降低至 4.17 秒,有將近 100% 的提速!同時(shí),你可以不必等待整個(gè) ZIP 下載解壓完,而是在解壓完一小部分?jǐn)?shù)據(jù)的時(shí)候,就直接展示 UI。用戶側(cè)看起來就好像一瞬間就解壓完了。

因此,流式解壓可以應(yīng)用在許多時(shí)間敏感的操作里,也可以用來優(yōu)化基于 ZIP 文件的相關(guān)業(yè)務(wù)。例如基于 ZIP 的全局換膚加速、基于 ZIP 的 Web 資源緩存加載的加速等等。前言中的優(yōu)酷繪本秒開就是基于這一技術(shù)實(shí)現(xiàn)。

參考

[1]https://houbb.github.io/2018/11/09/althgorim-compress-althgorim-12-zip-02[2]AES Encryption Information: Encryption Specification AE-1 and AE-2https://www.winzip.com/win/en/aes_info.html[3]ZIP File Format Specificationhttps://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.2.1.TXT[4]AES Coding Tips for Developershttps://www.winzip.com/win/en/aes_tips.html

【本文為51CTO專欄作者“阿里巴巴官方技術(shù)”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

??戳這里,看該作者更多好文??

 

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2021-05-08 00:00:27

JavaScript ZIP文件

2015-04-08 15:40:53

php在線解壓解壓zip文件

2024-01-04 12:47:00

Linux命令工具

2018-02-28 13:20:40

Python解壓zip

2009-12-30 16:46:09

Ubuntu orac

2011-12-30 11:14:41

Javazip

2021-12-10 15:22:26

Go Zip 文件

2019-10-17 17:15:01

Linux解壓文件命令

2011-08-15 14:07:53

Objective-C解壓縮ZIP文件

2012-12-26 09:31:44

C#Winform

2012-05-10 09:43:28

2024-04-01 00:05:00

ChatGPTSSE

2021-01-03 09:44:34

解壓軟件解壓神器應(yīng)用

2010-01-04 10:36:34

ubuntu Json

2010-01-07 16:34:08

Ubuntu apac

2024-01-19 16:37:17

Linux操作系統(tǒng)

2010-01-08 14:13:14

Ubuntu 8.10

2010-01-07 16:47:01

2010-04-19 16:34:29

Unix操作系統(tǒng)

2015-10-12 08:53:49

程序員壓力
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)