2016-10-12 24 views
0

以下のコードを使用してAzure Blobストレージコンテナに画像をアップロードできます。ただし、既定では、格納されているファイルのContentTypeapplication/octet-streamに設定されています。これをimage/jpgに変更します。Azure BlobをREST API経由でアップロードするときcontentTypeを設定できません

これを行うには、以下のコメントの行を書きました。彼らはAzuredocumentationから理解している限り、必要なコンテンツタイプヘッダーを設定しましたが、今要求は200の代わりに403 Unauthorizedという応答になります。

private static void PutBlob(string filenameToSave) 
{ 
    var requestMethod = "PUT"; 
    var urlPath = _storageContainer + "/" + filenameToSave; 
    var storageServiceVersion = "2015-12-11"; 
    var date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture); 
    var blobType = "BlockBlob"; 
    var imageBytes = GetImageBytes(); 
    var canonicalizedResource = "/" + _storageAccount + "/" + urlPath; 

    // DOESN'T WORK: 
    var canonicalizedHeaders = "x-ms-blob-type:" + blobType + "\nx-ms-blob-content-type:image/jpeg\nx-ms-date:" + date + "\nx-ms-version:" + storageServiceVersion; 
    // WORKS: 
    //var canonicalizedHeaders = "x-ms-blob-type:" + blobType + "\nx-ms-date:" + date + "\nx-ms-version:" + storageServiceVersion; 

    // DOESN'T WORK: 
    string stringToSign = requestMethod + "\nimage/jpeg\n\n" + imageBytes.Length + "\n\n\n\n\n\n\n\n\n" + canonicalizedHeaders + "\n" + canonicalizedResource; 
    // WORKS: 
    //string stringToSign = requestMethod + "\n\n\n" + imageBytes.Length + "\n\n\n\n\n\n\n\n\n" + canonicalizedHeaders + "\n" + canonicalizedResource; 

    string authorizationHeader = GenerateSharedKey(stringToSign, _storageKey, _storageAccount); 

    var uri = $"https://{_storageAccount}.blob.core.windows.net/{urlPath}"; 
    var request = (HttpWebRequest)WebRequest.Create(uri); 
    request.Method = requestMethod; 
    request.ContentType = "image/jpeg"; // DOESN'T WORK 

    request.Headers.Add("x-ms-blob-content-type", "image/jpeg"); // DOESN'T WORK 
    request.Headers.Add("x-ms-blob-type", blobType); 
    request.Headers.Add("x-ms-date", date); 
    request.Headers.Add("x-ms-version", storageServiceVersion); 
    request.Headers.Add("Authorization", authorizationHeader); 

    var stream = request.GetRequestStream(); 
    stream.Write(imageBytes, 0, imageBytes.Length); 

    using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
    { 
     // check the response status here, 200/201 means it worked 

     Console.WriteLine("File uploaded"); 
    } 
} 

private static string GenerateSharedKey(string stringToSign, string key, string account) 
{ 
    string signature; 
    var unicodeKey = Convert.FromBase64String(key); 
    using (var hmacSha256 = new HMACSHA256(unicodeKey)) 
    { 
     var dataToHmac = Encoding.UTF8.GetBytes(stringToSign); 
     signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac)); 
    } 
    return string.Format(CultureInfo.InvariantCulture, "{0} {1}:{2}", "SharedKey", account, signature); 
} 

私は、問題が発生したauthorizationHeaderであることがわかりますが、私はガイドに従っていると、なぜ私が見ることができません。誰も私にこれについていくつかの光を当てることができますか?

また、Microsoft.WindowsAzure.Storageライブラリではなく、REST APIを使用してこれを行う必要があることにも注意してください(厄介なことに、このようにコードを実行すると分かります)。

ありがとうございました。

答えて

1

私はあなたのコード内の1つの問題を発見:

// DOESN'T WORK: 
    string stringToSign = requestMethod + "\nimage/jpeg\n\n" + imageBytes.Length + "\n\n\n\n\n\n\n\n\n" + canonicalizedHeaders + "\n" + canonicalizedResource; 

基本的にContentTypeは、第二のパラメータであってはなりません。第二のパラメータは、あなたがこれを変更する一度だから、あなたのコードは動作するはずですdocumentation

StringToSign = VERB + "\n" + 
       Content-Encoding + "\n" + 
       Content-Language + "\n" + 
       Content-Length + "\n" + 
       Content-MD5 + "\n" + 
       Content-Type + "\n" + 
       Date + "\n" + 
       If-Modified-Since + "\n" + 
       If-Match + "\n" + 
       If-None-Match + "\n" + 
       If-Unmodified-Since + "\n" + 
       Range + "\n" + 
       CanonicalizedHeaders + 
       CanonicalizedResource; 

に基づいてContent-Encodingです:

 string stringToSign = requestMethod + "\n" + 
      "\n" + //Content Encoding 
      "\n" + //Content Language 
      imageBytes.Length + "\n" + //Content Length 
      "\n" + //Content MD5 
      "image/jpeg" + "\n" + //Content Type 
      "\n" + //Date 
      "\n" + //If - Modified - Since 
      "\n" + //If - Match 
      "\n" + //If - None - Match 
      "\n" + //If - Unmodified - Since 
      "\n" + //Range + 
      canonicalizedHeaders + "\n" + 
      canonicalizedResource; 

また、あなたはContent-Typex-ms-blob-content-typeの両方を指定する必要はありません。 x-ms-blob-content-typeを定義する場合は、canonicalizedHeadersに含める必要があります。

private static void PutBlob(string filenameToSave) 
    { 
     var requestMethod = "PUT"; 
     var urlPath = "<container-name>" + "/" + filenameToSave; 
     var storageServiceVersion = "2015-12-11"; 
     var date = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture); 
     var blobType = "BlockBlob"; 
     var imageBytes = File.ReadAllBytes(@"File Path"); 
     var canonicalizedResource = "/" + accountName + "/" + urlPath; 

     // DOESN'T WORK: 
     //var canonicalizedHeaders = "x-ms-blob-type:" + blobType + "\nx-ms-blob-content-type:image/jpeg\nx-ms-date:" + date + "\nx-ms-version:" + storageServiceVersion; 
     // WORKS: 
     var canonicalizedHeaders = "x-ms-blob-type:" + blobType + "\nx-ms-date:" + date + "\nx-ms-version:" + storageServiceVersion + "\n"; 

     // DOESN'T WORK: 
     //string stringToSign = requestMethod + "\nimage/jpeg\n\n" + imageBytes.Length + "\n\n\n\n\n\n\n\n\n" + canonicalizedHeaders + "\n" + canonicalizedResource; 
     // WORKS: 
     //string stringToSign = requestMethod + "\n\n\n" + imageBytes.Length + "\n\n\n\n\n\n\n\n\n" + canonicalizedHeaders + "\n" + canonicalizedResource; 
     string stringToSign = requestMethod + "\n" + 
      "\n" + //Content Encoding 
      "\n" + //Content Language 
      imageBytes.Length + "\n" + //Content Length 
      "\n" + //Content MD5 
      "image/jpeg" + "\n" + //Content Type 
      "\n" + //Date 
      "\n" + //If - Modified - Since 
      "\n" + //If - Match 
      "\n" + //If - None - Match 
      "\n" + //If - Unmodified - Since 
      "\n" + //Range + 
      canonicalizedHeaders + 
      canonicalizedResource; 
     string authorizationHeader = GenerateSharedKey(stringToSign, accountKey, accountName); 

     var uri = "https://" + accountName + ".blob.core.windows.net/" + urlPath; 

     var request = (HttpWebRequest)WebRequest.Create(uri); 
     request.Method = requestMethod; 
     request.ContentType = "image/jpeg"; // DOESN'T WORK 

     //request.Headers.Add("x-ms-blob-content-type", "image/jpeg"); // DOESN'T WORK 
     request.Headers.Add("x-ms-blob-type", blobType); 
     request.Headers.Add("x-ms-date", date); 
     request.Headers.Add("x-ms-version", storageServiceVersion); 
     request.Headers.Add("Authorization", authorizationHeader); 

     var stream = request.GetRequestStream(); 
     stream.Write(imageBytes, 0, imageBytes.Length); 

     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 
      // check the response status here, 200/201 means it worked 

      Console.WriteLine("File uploaded"); 
     } 
    } 
+0

感謝のGaurav:

ここで私はこれをテストするために使用するコードです。間違った位置にあるコンテンツタイプとそれを混乱させていた 'ms-blob-content-type'の組み合わせでした。 –

関連する問題