Azure 存儲的斷點續傳與 MD5 校驗Azure 存儲的斷點續傳與 MD5 校驗問題分析首先關于 Azure 存儲中 MD5 的描述,我們已經有相關的介紹文檔,如果對于存儲中 MD5 的描述不熟悉,可以先參考 Azure Blob 存儲基于 MD5 的完整性檢查的內容。如果直接將文件上傳到 Blob 中可以在上傳的......
問題分析
首先關于 Azure 存儲中 MD5 的描述,我們已經有相關的介紹文檔,如果對于存儲中 MD5 的描述不熟悉,可以先參考 Azure Blob 存儲基于 MD5 的完整性檢查的內容。
如果直接將文件上傳到 Blob 中可以在上傳的方法中配置 BlobRequestOptions 類,將該類的 StoreBlobContentMD5 參數設置為 true,即可在上傳時自動計算 MD5 值并將此值寫入到請求頭部(ContentMD5)中(可以參考 BlobRequestOptions.StoreBlobContentMD5 Property 此文檔的描述)。 但是如果使用斷點續傳的方法,是將文件分為多個塊上傳,之后通過 PubBlockList 請求完成組合,那么想要上傳 MD5 值,需要在 PubBlockList 請求的頭部添加 xmsblobcontentmd5 參數,但是在 sdk 相關的方法中,BlobRequestOptions 中并沒有關于該參數的屬性,所以如果使用斷點續傳,采用 sdk 的 PubBlockList() 方法無法將 MD5 值上傳上去,本篇文檔即要解決如何在斷點續傳時上傳 MD5 值的問題。
解決方案
可以通過使用 REST API 的方式來解決此問題:
1.首先我們需要計算出文件的 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=blockblockid= + blobid;
String storageServiceVersion = 20150221;
String dateInRfc1123Format = DateTime.UtcNow.ToString(R, CultureInfo.InvariantCulture);
Int32 blobLength = blobContent.Length;
//headers
String canonicalizedHeaders = String.Format(
\nxmsdate:{0}\nxmsversion:{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[xmsdate] = dateInRfc1123Format;
request.Headers[xmsversion] = 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 值和 xmsblobcontentmd5 寫入到請求頭中:
public async Task PutBlobListAsync(String containerName, String blobName, Liststring blobIdList, string md5, bool error = false)
{
String requestMethod = PUT;
String urlPath = String.Format({0}/{1}, containerName, blobName) + ?comp=blocklist;
String storageServiceVersion = 20150221;
String dateInRfc1123Format = DateTime.UtcNow.ToString(R, CultureInfo.InvariantCulture);
String canonicalizedHeaders = String.Format(
\nxmsblobcontentmd5:{0}\nxmsdate:{1}\nxmsversion:{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[xmsblobcontentmd5] = md5;
request.Headers[xmsdate] = dateInRfc1123Format;
request.Headers[xmsversion] = 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);
}
}
}
}
完整示例請參考示例代碼。
特別聲明:以上文章內容僅代表作者本人觀點,不代表ESG跨境電商觀點或立場。如有關于作品內容、版權或其它問題請于作品發表后的30日內與ESG跨境電商聯系。
二維碼加載中...
使用微信掃一掃登錄
使用賬號密碼登錄
平臺顧問
微信掃一掃
馬上聯系在線顧問
小程序
ESG跨境小程序
手機入駐更便捷
返回頂部