Azure 存儲(chǔ)的斷點(diǎn)續(xù)傳與 MD5 校驗(yàn)

來源: Microsoft Azure
作者:Microsoft Azure
時(shí)間:2020-12-09
17471
本篇文檔即要解決如何在斷點(diǎn)續(xù)傳時(shí)上傳 MD5 值的問題。

show_bd3uWOLuAh-OBJAO9LKMGg8p8GnmJ272E4VgeSe9_EU.jpg

問題分析

首先關(guān)于 Azure 存儲(chǔ)中 MD5 的描述,我們已經(jīng)有相關(guān)的介紹文檔,如果對于存儲(chǔ)中 MD5 的描述不熟悉,可以先參考 Azure Blob 存儲(chǔ)基于 MD5 的完整性檢查的內(nèi)容。

如果直接將文件上傳到 Blob 中可以在上傳的方法中配置 BlobRequestOptions 類,將該類的 StoreBlobContentMD5 參數(shù)設(shè)置為 true,即可在上傳時(shí)自動(dòng)計(jì)算 MD5 值并將此值寫入到請求頭部(Content-MD5)中(可以參考 BlobRequestOptions.StoreBlobContentMD5 Property 此文檔的描述)。 但是如果使用斷點(diǎn)續(xù)傳的方法,是將文件分為多個(gè)塊上傳,之后通過 PubBlockList 請求完成組合,那么想要上傳 MD5 值,需要在 PubBlockList 請求的頭部添加 x-ms-blob-content-md5 參數(shù),但是在 sdk 相關(guān)的方法中,BlobRequestOptions 中并沒有關(guān)于該參數(shù)的屬性,所以如果使用斷點(diǎn)續(xù)傳,采用 sdk 的 PubBlockList() 方法無法將 MD5 值上傳上去,本篇文檔即要解決如何在斷點(diǎn)續(xù)傳時(shí)上傳 MD5 值的問題。

解決方案

可以通過使用 REST API 的方式來解決此問題:

1.首先我們需要計(jì)算出文件的 MD5 值:

string contentHash = md5()(File.ReadAllBytes(sourcePath));

2.將文件分塊上傳:

public async Task PutBlobAsync(String containerName, String blobName, byte[] blobContent, String blobid, bool error = false)

{

    String requestMethod = "PUT";

    String urlPath = String.Format("{0}/{1}", containerName, blobName) + "?comp=block&blockid=" + blobid;

    String storageServiceVersion = "2015-02-21";

    String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);


    Int32 blobLength = blobContent.Length;

    //headers

    String canonicalizedHeaders = String.Format(

        "\nx-ms-date:{0}\nx-ms-version:{1}",

        dateInRfc1123Format,

        storageServiceVersion);

    //resources

    String canonicalizedResource = String.Format("/{0}/{1}", AzureConstants.Account, String.Format("{0}/{1}", containerName, blobName) + "\nblockid:" + blobid + "\ncomp:block");

    String stringToSign = String.Format(

    "{0}\n\n\n{1}\n\n\n\n\n\n\n\n{2}\n{3}",

    requestMethod,

    blobLength,

    canonicalizedHeaders,

    canonicalizedResource);

    string authorizationHeader = CreateAuthorizationHeader(stringToSign);

    //上傳url

    Uri uri = new Uri(BlobEndPoint + urlPath);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.Method = requestMethod;

    request.Headers["x-ms-date"] = dateInRfc1123Format;

    request.Headers["x-ms-version"] = storageServiceVersion;

    request.Headers["Authorization"] = authorizationHeader;

    request.ContentLength = blobLength;


    try {

        using (Stream requestStream = await request.GetRequestStreamAsync()) {

            requestStream.Write(blobContent, 0, blobLength);

        }


        using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) {

            String ETag = response.Headers["ETag"];

            System.Console.WriteLine(ETag);

        }

        error = false;

    }

    catch (WebException ex) {

        System.Console.WriteLine("An error occured. Status code:" + ((HttpWebResponse)ex.Response).StatusCode);

        System.Console.WriteLine("Error information:");

        error = true;

        using (Stream stream = ex.Response.GetResponseStream()) {

            using (StreamReader sr = new StreamReader(stream)) {

                var s = sr.ReadToEnd();

                System.Console.WriteLine(s);

            }

        }

    }

}

3.在 PutBlobListAsync() 方法中將 MD5 值和 x-ms-blob-content-md5 寫入到請求頭中:

public async Task PutBlobListAsync(String containerName, String blobName, List<string> blobIdList, string md5, bool error = false)

{

    String requestMethod = "PUT";

    String urlPath = String.Format("{0}/{1}", containerName, blobName) + "?comp=blocklist";

    String storageServiceVersion = "2015-02-21";

    String dateInRfc1123Format = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture);


    String canonicalizedHeaders = String.Format(

        "\nx-ms-blob-content-md5:{0}\nx-ms-date:{1}\nx-ms-version:{2}",

        md5,

        dateInRfc1123Format,

        storageServiceVersion);

    StringBuilder stringbuilder = new StringBuilder();

    stringbuilder.Append("<BlockList>");

    foreach (string item in blobIdList) {

        stringbuilder.Append(" <Latest>" + item + "</Latest>");

    }

    stringbuilder.Append("</BlockList>");


    byte[] data = Encoding.UTF8.GetBytes(stringbuilder.ToString());


    Int32 blobLength = data.Length;

    String canonicalizedResource = String.Format("/{0}/{1}", AzureConstants.Account, String.Format("{0}/{1}", containerName, blobName) + "\ncomp:blocklist");

    String stringToSign = String.Format(

        "{0}\n\n\n{1}\n\n\n\n\n\n\n\n{2}\n{3}",

        requestMethod,

        blobLength,

        canonicalizedHeaders,

        canonicalizedResource);

    String authorizationHeader = CreateAuthorizationHeader(stringToSign);


    Uri uri = new Uri(BlobEndPoint + urlPath);

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

    request.Method = requestMethod;

    request.Headers["x-ms-blob-content-md5"] = md5;

    request.Headers["x-ms-date"] = dateInRfc1123Format;

    request.Headers["x-ms-version"] = storageServiceVersion;

    request.Headers["Authorization"] = authorizationHeader;

    request.ContentLength = blobLength;

    try {

        using (Stream requestStream = await request.GetRequestStreamAsync()) {

            requestStream.Write(data, 0, blobLength);

        }


        using (HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync()) {

            String ETag = response.Headers["ETag"];

            System.Console.WriteLine(ETag);

        }

        error = false;

    }

    catch (WebException ex) {

        System.Console.WriteLine("An error occured. Status code:" + ((HttpWebResponse)ex.Response).StatusCode);

        System.Console.WriteLine("Error information:");

        error = true;

        using (Stream stream = ex.Response.GetResponseStream()) {

            using (StreamReader sr = new StreamReader(stream)) {

                var s = sr.ReadToEnd();

                System.Console.WriteLine(s);

            }

        }

    }

}

完整示例請參考示例代碼。

立即登錄,閱讀全文
版權(quán)說明:
本文內(nèi)容來自于Microsoft Azure,本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對觀點(diǎn)贊同或支持。如有侵權(quán),請聯(lián)系管理員(zzx@kchuhai.com)刪除!
相關(guān)文章
Azure Arc為企業(yè)構(gòu)建安全的云基礎(chǔ)
Azure Arc為企業(yè)構(gòu)建安全的云基礎(chǔ)
隨著人工智能技術(shù)持續(xù)重塑企業(yè)運(yùn)營方式,企業(yè)需要能夠處理海量數(shù)據(jù)的系統(tǒng),以支持實(shí)時(shí)洞察,同時(shí)幫助他們應(yīng)對跨IT和OT環(huán)境(包括云端、邊緣和本地)中運(yùn)營、應(yīng)用、數(shù)據(jù)和基礎(chǔ)設(shè)施的協(xié)作難題。
Azure
微軟云
云服務(wù)
2024-12-172024-12-17
釋放.NET 9和Azure的AI技術(shù)與云計(jì)算潛力:更快、更智能、面向未來
釋放.NET 9和Azure的AI技術(shù)與云計(jì)算潛力:更快、更智能、面向未來
.NET 9現(xiàn)已正式發(fā)布,它為.NET平臺的發(fā)展掀開了嶄新的一頁,突破了性能、云原生開發(fā)和AI技術(shù)集成的邊界。
Azure
微軟云
云服務(wù)
2024-12-162024-12-16
Azure網(wǎng)絡(luò)管理現(xiàn)已具備智能Microsoft Copilot副駕駛能力
Azure網(wǎng)絡(luò)管理現(xiàn)已具備智能Microsoft Copilot副駕駛能力
智能Microsoft Copilot副駕駛for Azure網(wǎng)絡(luò)服務(wù)現(xiàn)已推出公共預(yù)覽版。
Azure
微軟云
云服務(wù)
2024-12-102024-12-10
Microsoft Fabric功能更新,借助AI驅(qū)動(dòng)的數(shù)據(jù)平臺加速應(yīng)用創(chuàng)新
Microsoft Fabric功能更新,借助AI驅(qū)動(dòng)的數(shù)據(jù)平臺加速應(yīng)用創(chuàng)新
一年前,我們正式推出了一款端到端數(shù)據(jù)平臺,旨在幫助組織推動(dòng)人工智能轉(zhuǎn)型,并重新定義數(shù)據(jù)的連接、管理和分析方式。
Azure
微軟云
云服務(wù)
2024-12-092024-12-09
優(yōu)質(zhì)服務(wù)商推薦
更多
掃碼登錄
打開掃一掃, 關(guān)注公眾號后即可登錄/注冊
加載中
二維碼已失效 請重試
刷新
賬號登錄/注冊
個(gè)人VIP
小程序
快出海小程序
公眾號
快出海公眾號
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家