Jesus
Jesus

Reputation: 475

Upload blob storage return issues trying to upload local container

I want to implement Azurite + Microsoft Azure Storage Explorer.

First of all, I Installed Azurite globally, and after that, I run azurite run command. Once I did with that I connect it via Microsoft Azure Storage Explorer as a Local Storage Emulator and inside it, I created a container as image below:

enter image description here

Now I want to upload an image using the service in C#, so I installed Azure.Storage.Blobs v12.14.1 library and try:

Controller

    [HttpPost]
    public async Task<IActionResult> Create()
    {
        var files = HttpContext.Request.Form.Files;
        var result = _blobHelper.Save(files);
        if (result.Result != "Ok")
        {
            return RedirectToAction("Index", "Test");
        }
    }

Helper:

[HttpPost]
    public async Task<string> Save(IFormFileCollection files)
    {
        var isUploaded = false;

        try
        {
            if (files.Count == 0)
                return "No files received from the upload.";

            if (
                string.IsNullOrEmpty(_azureStorageConfig.AccountKey)
                || string.IsNullOrEmpty(_azureStorageConfig.AccountName)
            )
                return "sorry, can't retrieve your azure storage details from appsettings.js, make sure that you add azure storage details there";

            if (string.IsNullOrEmpty(_azureStorageConfig.ImageContainer))
                return "Please provide a name for your image container in the azure blob storage";

            foreach (var formFile in files)
            {
                if (formFile.Length > 0)
                {
                    await using var stream = formFile.OpenReadStream();

                    isUploaded = await UploadFileToStorage(
                        stream,
                        formFile.FileName,
                        _azureStorageConfig
                    );
                }
            }

            if (isUploaded)
            {
                return "Ok";
            }
            else
            {
                return "Look like the image couldnt upload to the storage";
            }
        }
        catch (Exception ex)
        {
            return $"{ex.Message}";
        }
    }

  public static async Task<bool> UploadFileToStorage(
        Stream fileStream,
        string fileName,
        AzureStorageConfig _storageConfig
    )
    {
        // Create a URI to the blob
        var blobUri = new Uri(
            "http://"
                + _storageConfig.AccountName
                + ".blob.core.windows.net/"
                + _storageConfig.ImageContainer
                + "/"
                + fileName
        );

        // Create StorageSharedKeyCredentials object by reading
        // the values from the configuration (appsettings.json)
        var storageCredentials = new StorageSharedKeyCredential(
            _storageConfig.AccountName,
            _storageConfig.AccountKey
        );

        // Create the blob client.
        var blobClient = new BlobClient(blobUri, storageCredentials);
       

        var fileBytes = ReadFully(fileStream);
        var data = new BinaryData(fileBytes);

        // Upload the file
        await blobClient.UploadAsync(data);

        return await Task.FromResult(true);
    }

    private static byte[] ReadFully(Stream input)
    {
        using var ms = new MemoryStream();
        input.CopyTo(ms);
        return ms.ToArray();
    }

My credentials looks like:

enter image description here

The problem start when it tries to upload the blob in this line:

await blobClient.UploadAsync(data);

it returns to controller and show the following result:

Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:ee3c9ac1-301e-00ec-33fc-083eaf000000 Time:2022-12-05T22:55:43.9223139Z Status: 403 (Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.) ErrorCode: AuthenticationFailed

Additional Information: AuthenticationErrorDetail: The MAC signature found in the HTTP request '1uuge8Zz1qo2rnSAj7nCyN+IE6NgjmeBqa5CL4Wl9fM=' is not the same as any computed signature. The server used the following string to sign: 'PUT

What am I doing wrong or am I missing something?

UPDATE I updated the blob URI for:

  var blobUri = new Uri(
            "http://127.0.0.1:10000/"  //azurite blob service
                + _storageConfig.AccountName
                + _storageConfig.ImageContainer
                + "/"
                + fileName
        );

Apparently the issue above gone, but now it is throwing a new error

The specifed resource name contains invalid characters.

It can be the binary data values?

enter image description here

UPDATE 2

I added + ".blob.core.windows.net/" to Uri as:

var blobUri = new Uri(
            "http://127.0.0.1:10000/"
                + _storageConfig.AccountName
                + ".blob.core.windows.net/"
                + _storageConfig.ImageContainer
                + "/"
                + fileName
        );

And now is throwing:

Invalid storage account. RequestId:f42a80d9-9876-4c08-9c3a-32c93d112ffc Time:2022-12-06T02:13:09.876Z Status: 400 (Invalid storage account.) ErrorCode: InvalidOperation

Content: InvalidOperation Invalid storage account. RequestId:f42a80d9-9876-4c08-9c3a-32c93d112ffc Time:2022-12-06T02:13:09.876Z

Headers: Server: Azurite-Blob/3.20.1 x-ms-error-code: InvalidOperation x-ms-request-id: f42a80d9-9876-4c08-9c3a-32c93d112ffc Date: Tue, 06 Dec 2022 02:13:09 GMT Connection: keep-alive Keep-Alive: REDACTED Transfer-Encoding: chunked Content-Type: application/xml

AppSettings.json:

"AzureStorageConfig": {
    "AccountName": "devstoreaccount1",
    "AccountKey": "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==",
    "ImageContainer": "my-container",
    "ConnectionString": "DefaultEndPoints=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
  },

UPDATE 3

After the comments below, it returns the auth issue again

Make sure the value of the Authorization header is formed correctly including the signature.

Headers: Server: Azurite-Blob/3.20.1 x-ms-error-code: AuthorizationFailure x-ms-request-id: bbd5ed42-1b34-4a34-8bfe-4457a883a0e1 Date: Tue, 06 Dec 2022 14:07:57 GMT Connection: keep-alive Keep-Alive: REDACTED Transfer-Encoding: chunked Content-Type: application/xml

Upvotes: 0

Views: 830

Answers (1)

SwethaKandikonda
SwethaKandikonda

Reputation: 8234

UPDATE 2

I added + ".blob.core.windows.net/" to Uri as:

var blobUri = new Uri(
          "http://127.0.0.1:10000/"
              + _storageConfig.AccountName
              + ".blob.core.windows.net/"
              + _storageConfig.ImageContainer
              + "/"
              + fileName
      );

The Blob URI format for Local Storage will be "http://127.0.0.1:10000/"+<Account_Name>+"/"+<Container_Name>+"/"+<File_Name> but not as you have mentioned in update 2.

enter image description here

As per the code you have mentioned in Update 1, the correct format of the Blob URI would be "http://127.0.0.1:10000/"+<Account_Name>+"/"+<Container_Name>+"/"+<File_Name>. But I see you have mentioned it as "http://127.0.0.1:10000/"+<Account_Name>+<Container_Name>+"/"+<File_Name> and hence it is taking the file name to be Container Name which is resulting in The specifed resource name contains invalid characters. Make sure you update Blob URI part with below code.

var blobUri = new Uri(
            "http://127.0.0.1:10000/"  
                + _storageConfig.AccountName
                + "/"
                + _storageConfig.ImageContainer
                + "/"
                + fileName
        );

Upvotes: 0

Related Questions