Reputation: 475
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
Upvotes: 0
Views: 830
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.
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