Create file on azure storage in Business Central

RahilaRahila Member Posts: 16
edited 2020-01-13 in NAV Three Tier
I am trying to create a file on azure storage using PUT request, Below is my code and i get the error The value for one of the HTTP headers is not in the correct format.

The Code and the headers formed are:
procedure CreateFileNew(FileName: Text)
var
requestMethod: Text;
request: HttpRequestMessage;
RequestHeader: HttpHeaders;
hhtpres: HttpResponseMessage;
canonicalizedResource: Text;
canonicalizedHeaders: Text;
urlPath: Text;
client: HttpClient;
content: HttpContent;
test: Boolean;
MethodType: Text;
authorizationHeader: Text;
stringToSign: Text;
msVersion: Text;
cha: Char;
contenttype: Text;
contentLength: Integer;
dat: DateTime;
res: Text;
keyss: Text;
dateInRfc1123Format: DateTime;
EncryptionManagement: Codeunit "Encryption Management";
begin
cha := 13;
msVersion := '2015-04-05';//;'02-14-2014';
MethodType := 'CreateFile';
keyss := 'i0PNZ6Ykse7oSSfUzFeA36rQfAvaaJiL9LYbv9UZnol0NRM4sal4s8B3ipkjvfzcsP8/gnI58G6A==';
dateInRfc1123Format := CurrentDateTime;
requestMethod := 'PUT';
urlPath := 'lables/' + 'tre11.csv';
canonicalizedResource := '/bcstorage/lables/tre11.csv';
canonicalizedHeaders := 'x-ms-date:' + Format(dateInRfc1123Format) + Format(cha) + 'x-ms-range:bytes=0-1024' + Format(cha) + 'x-ms-version:' + msVersion
+ Format(cha) + 'x-ms-write:update' + Format(cha);
//canonicalizedHeaders := 'x-ms-content-length:1024' + Format(cha) + 'x-ms-date:' + FORMat(dateInRfc1123Format) + Format(cha) + 'x-ms-type:file' + Format(cha) + 'x-ms-version:' + msVersion;
stringToSign := (requestMethod + Format(cha) + Format(cha) + Format(cha) + Format(cha) + Format(cha)
+ Format(cha) + Format(cha) + Format(cha) +
Format(cha) + Format(cha) + Format(cha) + Format(cha) + canonicalizedHeaders + canonicalizedResource);


authorizationHeader := 'SharedKey bc365storage:' + EncryptionManagement.GenerateBase64KeyedHashAsBase64String(stringToSign, keyss, 2);
Message((authorizationHeader));
request.SetRequestUri('https://bcstorage.file.core.windows.net/lables/tre11.csv');
request.Method := requestMethod;
RequestHeader.Add('x-ms-date', FORMat(dateInRfc1123Format));
RequestHeader.Add('x-ms-version', msVersion);
RequestHeader.Add('Authorization', authorizationHeader);
RequestHeader.Add('Accept-Charset', 'UTF-8');
if MethodType = 'CreateFile' then begin
RequestHeader.Add('x-ms-content-length', '1024');
RequestHeader.Add('x-ms-type', 'file');
end;

client.Put('https://bcstorage.file.core.windows.net/lables/tre11.csv', content, hhtpres);
hhtpres.Content.ReadAs(res);
Message(res);
test := client.Send(request, hhtpres);
end;

Best Answers

Answers

  • RahilaRahila Member Posts: 16
    ftornero wrote: »
    Hello @Rahila

    I changed your code a little to make it works

    The EncryptionManagement codeunit changed in BC15 and I added some procedures to get your account data and the DateTime format expected.
    codeunit 50124 CreateFileNew
    {
        procedure CreateFileNew(FileName: Text)
        var
            requestMethod: Text;
            request: HttpRequestMessage;
            RequestHeader: HttpHeaders;
            hhtpres: HttpResponseMessage;
            canonicalizedResource: Text;
            canonicalizedHeaders: Text;
            urlPath: Text;
            client: HttpClient;
            content: HttpContent;
            test: Boolean;
            MethodType: Text;
            authorizationHeader: Text;
            stringToSign: Text;
            msVersion: Text;
            cha: Char;
            contenttype: Text;
            contentLength: Integer;
            dat: DateTime;
            res: Text;
            keyss: Text;
            dateInRfc1123Format: Text;  // <------------ Changed
            //EncryptionManagement: Codeunit "Encryption Management";
            EncryptionManagement: Codeunit "Cryptography Management";   // <------------ Changed BC15    
            uri: Text;
        begin
            cha := 10; //13;  <------------ Changed
            msVersion := '2015-02-21';//'2015-04-05';//;'02-14-2014'; <------------ Changed
            MethodType := 'CreateFile';
            keyss := GetAccountAccessKey();
            dateInRfc1123Format := GetUTCDateTimeText(); // <------------ Changed
            requestMethod := 'PUT';
            urlPath := GetAccountSharedRessource() + '/lables/' + FileName; // you need a folder lables inside your Shared ressource
            //canonicalizedResource := '/bcstorage/lables/tre11.csv';
            CanonicalizedResource := StrSubstNo('/%1/%2', GetAccountName(), urlPath);
            canonicalizedHeaders := 'x-ms-content-length:' + '1024' + Format(cha) +
                                    'x-ms-date:' + dateInRfc1123Format + Format(cha) +
                                    'x-ms-type:' + 'file' + Format(cha) +
                                    'x-ms-version:' + msVersion;
    
            stringToSign := (requestMethod + Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             Format(cha) +
                             canonicalizedHeaders + Format(cha) + // <------------ Changed
                             canonicalizedResource);
    
            authorizationHeader := 'SharedKey ' + GetAccountName() + ':' + EncryptionManagement.GenerateBase64KeyedHashAsBase64String(stringToSign, keyss, 2);
            //Message((authorizationHeader));
            uri := StrSubstNo('https://%1.file.core.windows.net/%2', GetAccountName(), urlPath);
            request.SetRequestUri(uri);
            request.Method := requestMethod;
            RequestHeader.Clear();
            request.GetHeaders(RequestHeader);
            RequestHeader.Add('Authorization', authorizationHeader);
            RequestHeader.Add('x-ms-content-length', '1024');
            RequestHeader.Add('x-ms-date', dateInRfc1123Format);
            RequestHeader.Add('x-ms-type', 'file');
            RequestHeader.Add('x-ms-version', msVersion);
    
            client.Send(request, hhtpres);
            if not hhtpres.IsSuccessStatusCode then
                Error(hhtpres.ReasonPhrase);
        end;
    
        procedure GetUTCDateTimeText(): Text
        var
            TypeHelper: Codeunit "Type Helper";
        begin
            exit(TypeHelper.GetCurrUTCDateTimeAsText());
        end;
    
        procedure GetAccountName(): Text
        begin
            // Your Account name
            exit('bc365storage');
        end;
    
        procedure GetAccountSharedRessource(): Text
        begin
            // Your Shared ressource
            exit('bcstorage');        
        end;
    
        procedure GetAccountAccessKey(): Text
        begin
            // Your Access Key
            exit('i0PNZ6Ykse7oSSfUzFeA36rQfAvaaJiL9LYbv9UZnol0NRM4sal4s8B3ipkjvfzcsP8/gnI58G6A==');
        end;
    }
    

    Regards

    Thanks for the reply, But i am working on BC14 so i cannot find the codeunit "Cryptography Management" .
  • ftorneroftornero Member Posts: 307
    Hello @Rahila ,

    In this case you can use the codeunit that you are already using (Encryption Management).

    Regards.
  • RahilaRahila Member Posts: 16
    Hello @ftornero ,
    I am having this error now.


    A call to System.Convert.FromBase64String failed with this message: Invalid length for a Base-64 char array or string.
  • ftorneroftornero Member Posts: 307
    Hello @Rahila

    Well this happens because the Access Key you posted is not a valid one, I think that that was on purpose invalid,

    Check that that access key is your valid access key.
        procedure GetAccountAccessKey(): Text
        begin
            // Your Access Key
            exit('i0PNZ6Ykse7oSSfUzFeA36rQfAvaaJiL9LYbv9UZnol0NRM4sal4s8B3ipkjvfzcsP8/gnI58G6A==');
        end;
    

    Regards
  • RahilaRahila Member Posts: 16
    @ftornero The access key's sample is the same, my original access key is also in the same format.
  • ftorneroftornero Member Posts: 307
    Hello @Rahila ,

    And using your original access key you get the same error?

    Regards.
  • RahilaRahila Member Posts: 16
    @ftornero yes . The format is same as above i have just removed few characters.
  • RahilaRahila Member Posts: 16
    @ftornero it worked. What i need now is to write few contents too in the file. can you please help.
  • RahilaRahila Member Posts: 16
    @ftornero Thank you so much. You solved my problem.
Sign In or Register to comment.