Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload File with brackets ([ & ]) in the name

I'm moving a ClickOnce install from a regular web server to Azure Blob storage and have a problem with some of the files. The filenames contains [ ] and CloudBlob.UploadFile fails with an exception:

Microsoft.WindowsAzure.Storageclient.StorageException:
Error accessing blob storage: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.

The code has been used for a while and only fails on files with [ ] in the name so I don't believe that it is an "authentication failure". In this particular case, this is the seventh file being uploaded in a loop. I found this link on MSDN about valid file names and this on stack overflow which both show problems with square brackets in URL's and reference UrlEncode. I added in a call to UrlEncode and that did not help. The container is created with public access since we use it to support customer downloads of our software. We have been hosting a "test" install in another container and have not had permission problems accessing that either.

I can upload the file with no name changes and then rename the file to add the "path" using newdesic's Azure Storage Explorer tool so what is that doing that I am not doing?

like image 299
fp0n Avatar asked Jan 15 '23 20:01

fp0n


1 Answers

I see you're using the 1.7 SDK. This is a small encoding issue with the SDK which is also present in v2.0. Let's see what happens.

No encoding

account.CreateCloudBlobClient()
       .GetContainerReference("temp")
       .GetBlobReference("abc[]def.txt")
       .UploadFile("myfile.txt");

If you don't encode the blob name, you'll end up with a request to the following URL which is causing the authentication exception:

http://account.blob.core.windows.net/temp/abc[]def.txt

The is because the SDK uses Uri.EscapeUriString internally to encode your string, but this doesn't take into account square brackets.

Encoding

Then you would expect the following to do the trick:

account.CreateCloudBlobClient()
       .GetContainerReference("temp")
       .GetBlobReference(HttpUtility.UrlEncode("abc[]def.txt"))
       .UploadFile("myfile.txt");

The issue here is that you'll end up with this url:

http://account.blob.core.windows.net/temp/abc%255b%255ddef.txt

So what's happening here? Calling HttpUtility.UrlEncode turns abc[]def.txt to abc%5B%5Ddef.txt, which is correct. But internally, the SDK will encode this string again which results in abc%255b%255ddef.txt, which isn't what you want.

Workaround

The only way to apply encoding which takes square brackets into accounts is by using a small workaround. If you pass the full URL to the GetBlobReference method, the SDK assumes you did all the encoding yourself:

var container = account.CreateCloudBlobClient().GetContainerReference("temp");
var blob = container.GetBlobReference(String.Format("{0}/{1}", 
                container.Uri, System.Web.HttpUtility.UrlEncode("abc[]def.txt")));
blob.UploadFile("myfile.txt");

This results in a correctly encoded URL:

http://account.blob.core.windows.net/temp/abc%5b%5ddef.txt

And if you use a tool like CloudXplorer, you'll see the blob with the correct filename:

enter image description here

like image 93
Sandrino Di Mattia Avatar answered Jan 24 '23 09:01

Sandrino Di Mattia