简体   繁体   中英

Uploading a PDF File to Azure Blob Storage using REST API & C# (Without using any AZURE STORAGE SDKs)

I am trying to upload a file in to an Azure Storage Container using REST API, without using any SDKs.

Reason for not using the Azure.Storage.Blobs SDK is, it has a dependency on .netstandard2.0 and some of the DLLs referred by the SDK is not compatible when the project runs .NET Framework 4.6.1. I tried assembly binding redirect in the config and didn't workout well (System.ValueTuple.dll reference issue).

Hence i am trying to re-write my Upload code using C# and REST API without the SDK.

Here is code that i am trying

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

Code to invoke the Upload function

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

Exception is thrown while executing this line if (request.GetResponse() is HttpWebResponse response)

Exception Message: The remote server returned an error: (403) Forbidden.

I tried to simulate this request using PostMan and got this error message

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'

I tried the answers given in these links and it works if the file is a text file, but fails when tried with a pdf

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

Any help would be greatly appreciated.

Thanks Raghunathan S

you added an extra semicolon in this code:

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

please change to this:

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

Hope this can help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM