簡體   English   中英

通過REST API上傳Azure Blob時無法設置contentType

[英]Unable to set contentType when uploading Azure Blob via REST API

我具有以下代碼,該代碼已成功將圖像上傳到我的Azure Blob存儲容器。 但是,默認情況下,它將存儲文件的ContentType設置為application/octet-stream我想將其更改為image/jpg

為此,我在下面的注釋中寫了幾行。 據我從Azure 文檔中了解的內容,它們設置了所需的內容類型標頭,但是,該請求現在導致403 Unauthorized響應,而不是200

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 ,但是我無法理解為什么遵循了指南。 誰能幫我闡明一下。

還要注意,我必須通過REST API而不是Microsoft.WindowsAzure.Storage庫來完成此操作(令人討厭的是,因為我知道這樣做是代碼的一小部分)。

謝謝。

我在您的代碼中發現了一個問題:

// 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 Content-Encoding

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;

因此,一旦您對此進行了更改,您的代碼應該可以正常工作:

        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");
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM