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:
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:
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?
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.876ZHeaders: 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