【问题标题】:Uploading a PDF File to Azure Blob Storage using REST API & C# (Without using any AZURE STORAGE SDKs)使用 REST API 和 C# 将 PDF 文件上传到 Azure Blob 存储(不使用任何 AZURE STORAGE SDK)
【发布时间】:2020-12-02 15:28:55
【问题描述】:

我正在尝试使用 REST API 将文件上传到 Azure 存储容器,而不使用任何 SDK。

不使用 Azure.Storage.Blobs SDK 的原因是,它依赖于 .netstandard2.0,并且 SDK 引用的某些 DLL 在项目运行 .NET Framework 4.6.1 时不兼容。我在配置中尝试了程序集绑定重定向并且没有很好地锻炼(System.ValueTuple.dll 参考问题)。

因此,我尝试在没有 SDK 的情况下使用 C# 和 REST API 重写我的上传代码。

这是我正在尝试的代码

public class AzureRestApi
{
        private string _x_ms_client_request_id = string.Empty;

        private string _x_ms_date = string.Empty;

        public string AzureStorageAccountName { get; set; }

        public string AzureStorageAccessKey { get; set; }

        public string BlobSaveFolder
        {
            get; set;
        }

        public string X_MS_DATE
        {
            get
            {
                return _x_ms_date;
            }
        }

        public string X_MS_VERSION
        {
            get
            {
                return "2019-12-12";
            }
        }

        public string BaseURI
        {
            get
            {
                return string.Format("https://{0}.blob.core.windows.net/", AzureStorageAccountName);

            }
        }        

        public AzureRestApi()
        {
            //Date and GUID should be same that is used to create the key signing string and the one that is being sent in the 
            //header of REST api requests.
            _x_ms_date  = DateTime.UtcNow.ToString("R", CultureInfo.InvariantCulture); 
            _x_ms_client_request_id = System.Guid.NewGuid().ToString();
        }

        public bool UploadBlobToContainer(string filePath, string containerName)
        {
            bool isUploaded = false;

            try
            {
                FileInfo fileInfo = new FileInfo(filePath);
                long contentLength = fileInfo.Length;
                long range = contentLength - 1;
                string method = "PUT";
                string contentType = "application/pdf";
                string blobName = fileInfo.Name;
                string blobURI = BaseURI + containerName + "/" + blobName;
                string xmsHeader = $"x-ms-blob-type:BlockBlob\nx-ms-date:{X_MS_DATE};\nx-ms-version:{X_MS_VERSION}";
                string resHeader = $"/{AzureStorageAccountName}/{containerName}/{blobName}";

                if (WebRequest.Create(blobURI) is HttpWebRequest request)
                {
                    request.Method = method;
                    request.ContentType = contentType;
                    request.ContentLength = contentLength;
                    request.Headers.Add("x-ms-blob-type", "BlockBlob");
                    request.Headers.Add("x-ms-date", X_MS_DATE);
                    request.Headers.Add("x-ms-version", X_MS_VERSION);                    
                    request.Headers.Add("Authorization", GetAuthorizationHeader(method, xmsHeader, resHeader, request));

                    using (Stream requestStream = request.GetRequestStream())
                    {
                        byte[] fileContents = null;
                        using (FileStream fs = fileInfo.OpenRead())
                        {
                            fileContents = new byte[fs.Length];
                            fs.Read(fileContents, 0, fileContents.Length);
                            fs.Close();
                        }
                        requestStream.Write(fileContents, 0, fileContents.Length);
                    }

                    if (request.GetResponse() is HttpWebResponse response)
                    {
                        if (response.StatusCode == HttpStatusCode.OK)
                            isUploaded = true;
                        else
                            isUploaded = false;
                    }
                }
            }
            catch (Exception ex)
            {
                Log.LogException(ex);
            }
            return isUploaded;
        }

        private string GetAuthorizationHeader(string method, string xmsHeader, string resHeader, HttpWebRequest request)
        {
            string strToSign = $"{method}\n\n\n{request.ContentLength}\n\n{request.ContentType}\n\n\n\n\n\n\n{xmsHeader}\n{resHeader}";

            string signatureString = GetHashedString(strToSign, AzureStorageAccessKey);

            string authorizationHeader = string.Format(
                 CultureInfo.InvariantCulture,
                 "{0} {1}:{2}",
                 "SharedKey",
                 AzureStorageAccountName,
                 signatureString);

            return authorizationHeader;
        }
}

调用上传函数的代码

string storageName = "MyDefaultStorage";
            
string containerName = "MyDefaultContainer";
            
AzureRestApi restApi = new AzureRestApi()
{
    AzureStorageAccountName = storageName,
    
    AzureStorageAccessKey = "MY_STORAGE_ACCOUNT_ACCESS_KEY", 
};

restApi.UploadBlobToContainer("E:\\UploadFiles\\UploadDocument1.pdf", containerName);

执行此行时抛出异常 if (request.GetResponse() is HttpWebResponse response)

异常消息:远程服务器返回错误:(403) Forbidden。

我尝试使用 PostMan 模拟此请求并收到此错误消息

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

The MAC signature found in the HTTP request 'RW1ACnL1aYqtSnJeHhV2694Ek95Olnf+V3Eup4Jt5ng=' is not the same as any computed signature. Server used following string to sign: 'PUT



461804


application/pdf






x-ms-blob-type:BlockBlob
x-ms-date:Wed, 12 Aug 2020 19:30:20 GMT
x-ms-version:2019-12-12
/MyDefaultStorage/MyDefaultContainer/UploadDocument1.pdf'

我尝试了这些链接中给出的答案,如果文件是文本文件,它可以工作,但使用 pdf 尝试时失败

Azure rest api put blob REST Api to Azure blob storage using Access key

任何帮助将不胜感激。

谢谢 拉古纳坦 S

【问题讨论】:

    标签: c# azure-blob-storage azure-rest-api


    【解决方案1】:

    您在此代码中添加了一个额外的分号:

    string xmsHeader = $"x-ms-blob-type:BlockBlob\nx-ms-date:{X_MS_DATE};\nx-ms-version:{X_MS_VERSION}";
    

    请改成这样:

    string xmsHeader = $"x-ms-blob-type:BlockBlob\nx-ms-date:{X_MS_DATE}\nx-ms-version:{X_MS_VERSION}";
    

    希望对你有帮助。

    【讨论】:

    • 如果我的回答对您有帮助,您可以将其标记为已回答。非常感谢。
    • 感谢@Steve Zhao。它工作得很好。不知道我怎么错过了这个简单的细节。再次......谢谢。
    猜你喜欢
    • 2021-10-08
    • 2020-03-12
    • 2021-06-02
    • 2022-11-02
    • 2019-06-27
    • 2021-11-06
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    相关资源
    最近更新 更多