我們可以通過文件校驗值的方式來解決這種問題:通過專用工具,用不同計算方法(例如 MD5)對文件計算校驗值,隨後在需要時重新計算文件校驗值,並與最初的值對比。如果因為任何原因(網路問題、磁碟故障、病毒篡改)導致文件中哪怕有一個比特的內容有了變化,都會導致校驗值產生極大不同。而校驗值不同,就意味著文件受... ...
假設你是一位獨立軟體開發者,通過自己的網站提供軟體下載。網站完全托管在 Azure 中,並且軟體下載也是通過 Azure Blob 存儲和 Azure CDN 服務提供的。
這做法真不錯,不需要自己管理伺服器,就可以快速低成本地建立網站,並且用戶數量再多也不擔心網站撐不住了。
一個風和日麗的下午,你搞定了新版軟體開發,第一時間上傳到 Blob 存儲,等著用戶們下載升級。然而很快便收到消息:下載的新版沒法解壓縮,接著越來越多用戶反饋說遇到類似問題。
後來檢查發現,最初上傳到 Blob 的過程中,因為某種莫名其妙的原因,上傳的文件本身就是損壞的……
So,你下載上傳的文件
「真正」就是你需要的那個文件嗎?
我們可以通過文件校驗值的方式來解決這種問題:通過專用工具,用不同計算方法(例如 MD5)對文件計算校驗值,隨後在需要時重新計算文件校驗值,並與最初的值對比。如果因為任何原因(網路問題、磁碟故障、病毒篡改)導致文件中哪怕有一個比特的內容有了變化,都會導致校驗值產生極大不同。而校驗值不同,就意味著文件受損了!
因此為了避免上面提到的悲劇,你只需要:
1、在將文件上傳到 Azure Blob 存儲(或其他任何網路位置)前,在自己電腦上使用校驗工具算出文件的校驗值,並對上傳後的文件重新計算比較校驗值,確保上傳過程沒有導致文件損壞。
2、讓用戶下載你的文件同時,在網頁上提供文件校驗值。這樣有需要的用戶就可以在下載之後進行計算和比較,確保自己下載過程沒有導致文件損壞。
很多小伙伴可能舉手問我:怎樣計算文件的校驗值呢?此類工具非常多,微軟也提供了一個免費的工具。該工具支持通過 MD5 和 SHA-1 兩種計算方法計算文件的校驗值。
那麼,對於上傳到 Azure Blob 中的文件,如何實現自動計算和對比校驗值?難道每次都要自己重新下載進行對比麽?太麻煩了啊!
Azure Blob
可以自動幫你計算和對比 MD5 哦!
在上傳文件或者其他二進位內容到 Azure Blob 存儲時,可以利用請求中的 MD5 值來驗證內容完整性,而上傳成功後的 Blob 屬性裡面也會包含 MD5 這個屬性,以用作後續的驗證。
首先需要註意,完整性檢查是基於當前 REST 請求的,也就是說只會對當前上傳內容進行 MD5 值的計算和對比,因為 REST API 是無狀態的。
隨後要註意,基於 MD5 的完整性檢查,工作過程是這樣的:
1.(在上傳者本地)計算當前上傳內容的 MD5 值,
2. 在當前上傳文件的 REST 請求頭部(Content-MD5)設置該 MD5 值,
3. 服務端根據當前請求里的內容計算 MD5,並對比請求頭部中的 MD5 值,
4. 相同則驗證成功,並將該 MD5 值賦予 Blob 的 MD5 屬性,否則失敗。
最後,上傳到 Azure Blob 支持兩種方式,整體上傳和分塊上傳。可以採用整體上傳方式,一個請求完成;如果內容很大,比如幾個 GB,就需要分塊上傳,這時上傳分為多個請求,每個請求只上傳部分內容,這樣可以保證更高的效率和成功率。
如果是整體上傳,實際是調用 Put Blob 請求,這時上傳的內容就是文件完整內容,因此完全符合前面描述的MD5 完整性檢查工作過程,也就是最終既會做驗證,Blob 也會有 MD5 值。
但如果分塊上傳,實際是多個 Put Block 請求加上一個 Put Block List 請求組成。每個 Put Block 請求只上傳部分內容,因此這類請求里的 MD5 只能針對當前上傳內容,不能作為最終 Blob 的 MD5 值。而 Put Block List 請求的內容是一個列表,包含前面所有上傳 Block 的標識,因此這個請求里的 MD5 值也只能是對這個列表做完整性檢查。但是所有這些請求都驗證成功時可以保證內容的完整性。所以驗證是有的,但 Blob 沒有MD5 值。
目前出於性能考慮,Azure 存儲服務不會彙總前面請求里的所有 Block 的內容來計算整個 Blob 的 MD5 值,但提供了一個特殊的請求頭部 x-ms-blob-content-md5,服務端會將該頭部屬性值設置為 Blob 的 MD5 值。因此客戶端只要在最終的 Put Block List 請求里設置了整個內容的 MD5 值到 x-ms-blob-content-md5,就可以保證驗證,並且 Blob 也有 MD5 值。
因此分塊上傳基於 MD5 的完整性檢查的工作過程是:
1、將上傳文件分成多塊
2、將每一塊以 Put Block 請求發送,並計算當前塊的 MD5 值設置到 Content-MD5 頭部
3、當所有塊都發送完成後,發送 Put Block List 請求
-
計算整個上傳文件的 MD 值並設置到 x-ms-blob-content-md5 頭部
-
將前面發送的塊的標識組成列表作為請求的內容
-
計算塊標識列表的 MD5 值設置到 Content-MD5 頭部
4、對於所有請求,服務端根據當前請求里的內容計算 MD5,並對比請求頭部中的 Content-MD5 值,相同則驗證成功
5、然後將 Put Block List 請求里的 x-ms-blob-content-md5 的值賦予 Blob 的 MD5 屬性
總結來說,有兩個問題需要註意:
1/如何判斷是否做完整性驗證?
取決於請求的頭部 Content-MD5,有則驗證,否則無驗證。註意:
1.Put Blob 請求裡面 Content-MD5 和 x-ms-blob-content-md5 效果一樣。
2. 分塊上傳發送 Put Block List 請求時,如果把整個文件內容的 MD5 值設置給了 Content-MD5,那麼會驗證報錯。因為 Content-MD5 只用於當前請求內容的驗證。
2/如何判斷 Blob 是否包含 MD5 值?
整體上傳時,如果當前請求的 x-ms-version 大於等於 2012-02-12,那麼即使客戶端沒有設置 MD5 值,服務端也會自行計算並賦予 BlobMD5 屬性。
分塊上傳時,就取決於 x-ms-blob-content-md5 是否有值。