使用方括号([&])上传文件

fp0*_*p0n 4 azure azure-storage azure-storage-blobs azure-sdk-.net

我正在将ClickOnce安装从常规Web服务器移动到Azure Blob存储,并且某些文件存在问题.文件名包含[ ]CloudBlob.UploadFile失败,但有异常:

Microsoft.WindowsAzure.Storageclient.StorageException:
访问blob存储时出错:服务器无法验证请求.确保正确形成Authorization标头的值,包括签名.

代码已经使用了一段时间,并且只[ ]在名称中的文件上失败,因此我不认为它是"身份验证失败".在这种特殊情况下,这是在循环中上传的第七个文件.我在MSDN上发现了这个关于有效文件名的链接,这在堆栈溢出时发现了URL和引用中的方括号问题UrlEncode.我在电话中加入UrlEncode,但没有帮助.该容器是使用公共访问创建的,因为我们使用它来支持客户下载我们的软件.我们一直在另一个容器中托管"测试"安装,并且没有访问它的权限问题.

我可以上传没有更改名称的文件,然后使用newdesic的Azure存储资源管理器工具重命名该文件以添加"路径",那么我正在做什么呢?

San*_*tia 8

我看到你正在使用1.7 SDK.这是SDK的一个小编码问题,也存在于v2.0中.让我们看看发生了什么.

没有编码

account.CreateCloudBlobClient()
       .GetContainerReference("temp")
       .GetBlobReference("abc[]def.txt")
       .UploadFile("myfile.txt");
Run Code Online (Sandbox Code Playgroud)

如果不对blob名称进行编码,则最终会向以下URL发出请求,从而导致身份验证异常:

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

这是因为SDK在Uri.EscapeUriString内部使用来对您的字符串进行编码,但这并没有考虑方括号.

编码

然后你会期望以下方法来做到这一点:

account.CreateCloudBlobClient()
       .GetContainerReference("temp")
       .GetBlobReference(HttpUtility.UrlEncode("abc[]def.txt"))
       .UploadFile("myfile.txt");
Run Code Online (Sandbox Code Playgroud)

这里的问题是你最终会得到这个网址:

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

那么这里发生了什么?调用HttpUtility.UrlEncode将abc [] def.txt转换abc%5B%5Ddef.txt,这是正确的.但在内部,SDK将再次编码此字符串,导致abc%255b%255ddef.txt,这不是您想要的.

解决方法

将方括号应用于帐户的编码的唯一方法是使用一个小的解决方法.如果您将完整的URL传递给GetBlobReference方法,SDK会假定您自己完成了所有编码:

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");
Run Code Online (Sandbox Code Playgroud)

这会产生正确编码的URL:

http://account.blob.core.windows.net/temp/abc%5b%5ddef.txt
Run Code Online (Sandbox Code Playgroud)

如果你使用像CloudXplorer这样的工具,你会看到具有正确文件名的blob:

在此输入图像描述