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

时间:2012-12-03 15:49:31

标签: azure azure-storage azure-storage-blobs azure-sdk-.net

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

  

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

代码已经使用了一段时间,并且只在名称中带有[ ]的文件上失败,因此我不认为它是“身份验证失败”。在这种特殊情况下,这是在循环中上传的第七个文件。我找到了this link on MSDN about valid file namesthis on stack overflow which both show problems with square brackets in URL's and reference UrlEncode。我添加了对UrlEncode的电话,但没有帮助。该容器是使用公共访问创建的,因为我们使用它来支持客户下载我们的软件。我们一直在另一个容器中托管“测试”安装,并且没有访问它的权限问题。

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

2 个答案:

答案 0 :(得分:8)

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

无编码

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

如果您不对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");

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

  

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");

这会产生正确编码的网址:

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

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

enter image description here

答案 1 :(得分:1)

.Net 4.5中的Uri类有两个已知的中断

•'[',']'字符不再被转义

•'\'字符现在转义为%5C

当服务器尝试验证请求的签名时,这会导致身份验证,因为客户端和服务器上的规范化字符串现在不同。

当出现此问题时,客户端可以使用一些变通方法。正确的解决方案取决于您的具体应用和要求。 避免使用资源名称中的“[”,“]”或“\”字符 通过简单地避免这些字符,您将能够避免上述问题。

目标.Net 4.0

目前,建议客户只需继续将其应用程序定位到.Net 4.0,同时调查完整解决方案。请注意,由于.Net 4.5是一个升级版本,客户端仍然可以利用GC等方面的一些性能改进,而无需专门针对.Net 4.5配置文件。对于Windows RT开发人员,这不是一个选项,因此您需要下面详述的解决方法。

逃生前数据

如果可能,客户端可以预先转义数据或用不受影响的字符替换给定的字符。  这就是上面的解决方法正在发挥作用的原因。