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

  • Question

  • Hi 

    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.

    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 Method

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

    While executing this line of code 

      if (request.GetResponse() is HttpWebResponse response)

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

    Ran the inputs through PostMan and got these error details.

    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'


    Any help would be greatly appreciated.

    Thanks 

    Raghunathan S

    Wednesday, August 12, 2020 7:39 PM

Answers

  • Thank You Timon Yang.

    I figured out the issue. It is this line of code which caused the issue

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

    The extra ; after the {X_MS_DATE} is  the one which caused 403 error.

    After removing the ; it worked fine and PDF got uploaded successfully.

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

    Thanks 

    Raghunathan S

    • Marked as answer by Raghunathan S Thursday, August 13, 2020 7:22 AM
    Thursday, August 13, 2020 7:22 AM

All replies