我正在编写一个程序,从一个给定的AzureStorage帐户下载所有的数据和元数据。我几乎完成了帐户的文件部分,但在测试我的输出后,我遇到了一些奇怪的事情。
当我检查文件名中包含特殊字符的文件名时,例如& é #,AzureStorageFile.Uri方法返回的Uri与AzureStorage资源管理器中的Uri不同。
例如,一个名为& é #New Rich Text Document.rtf的文件
当我右键单击文件并单击属性时,该方法所需的Uri输出将是AzureStorage资源管理器提供的输出:http://accountname.file.core.windows.net/share/%26%20%C3%A9%20%23New%20Rich%20Text%20Document.rtf
但是在运行我的代码之后,我得到的结果如下:https://accountname.file.core.windows.net/share/& é %23New Rich Text Document.rtf
我猜一些特殊的字符在转换过程中没有被正确翻译,我没有在这个主题上发现类似的问题。
编辑: Fred Han确实给出了解决方案,但问题仍然存在,当我使用GetFileReference获取CloudFile时,它仍然具有带有特殊字符的Uri属性。执行File.FetchAttributes时,发送到服务器的请求使用了错误编码的File.Uri,并且我无法更改该属性的值
如果我尝试使用文件名的编码表示来获取文件名,那么在进行服务器请求时,CloudFile.Uri将被再次编码,这也将导致404.
我的目标是下载CloudFile,而不仅仅是获取URI,而且我无法做到这一点,因为请求将使用错误编码的URI
更新:我确实下载了该文件和所有其他包含特殊字符的文件,但我没有使用File.Uri属性来下载,因为它的编码很糟糕,而且我不能修改它的值。为此,我必须使用GetFileReference方法,但必须直接使用整个文件路径,而不仅仅是下面的答案/注释所指出的文件名。然后我必须手动更正文件路径,然后获取文件引用并下载它。
public CloudFile getFile()
{
CloudFileClient client = AzureWorker.Connector.FileClient;
CloudFileShare share = client.GetShareReference(ShareName);
CloudFileDirectory root = share.GetRootDirectoryReference();
string path = Uri.LocalPath.Substring(1, Uri.LocalPath.Length - 1);
int index = path.IndexOf('/');
path = path.Substring(index + 1, path.Length - index - 1).Replace("%25", "%");
index = path.LastIndexOf('/');
StringBuilder sb = new StringBuilder(path);
if (index != -1)
{
sb.Remove(index + 1, path.Length - index - 1);
sb.Append(FileName);
return root.GetFileReference(sb.ToString());
}
return root.GetFileReference(FileName);
}Uri是我的类中的CloudFile的Uri属性,FileName是我的类中的Cloudfile的Name属性,我认为在我的类中存储Uri就足够了,所以这个函数被设计为通过Uri和一些更正来获取正确的文件(适用于名称中包含特殊字符的文件夹)
感谢大家的帮助
发布于 2017-09-20 10:36:08
我使用下面的代码示例从一个名为sinequa-data的文件共享中获取一个名为& é #New Rich Text Document.rtf的文件的Uri,正如您所说的,Uri中的文件名不是URL编码的。但文件共享名称仍为sinequa-data,它不会以share形式返回。在使用fileClient.GetShareReference("{file_share_name}")获取共享引用时,应确保传递的文件共享名称是否正确。
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("{connection_string}");
CloudFileClient fileClient = storageAccount.CreateCloudFileClient();
CloudFileShare share = fileClient.GetShareReference("sinequa-data");
if (share.Exists())
{
CloudFileDirectory rootDir = share.GetRootDirectoryReference();
CloudFile file = rootDir.GetFileReference("& é %23New Rich Text Document.rtf");
if (file.Exists())
{
Console.WriteLine(file.Uri.ToString());
}
}

Azure存储资源管理器中文件的属性

此外,如果可能,您可以在将文件上载到文件共享之前对文件名进行编码。
编辑:
Azure存储资源管理器帮助我们对文件Uri中的文件名进行编码,但Azure存储SDK不执行此操作,如果要使Uri与Azure存储资源管理器返回的Uri相同,您可以尝试以下代码:
//Uri.EscapeUriString(file.Uri.ToString())
file.Share.Uri + "/" + Uri.EscapeUriString(file.Name).Replace("&", "%26")

更新:
首先,正如Michael Roberson提到的,我的文件名是& é %23New Rich Text Document.rtf,与你的文件名不同,所以如果你在你的程序中复制并运行我的代码,你会得到404错误。
此外,我将文件重命名为& é #New Rich Text Document.rtf并修改了代码,示例代码适用于我,您可以参考它。
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("{connection_string}");
CloudFileClient fileClient = storageAccount.CreateCloudFileClient();
List<CloudFileShare> fl = fileClient.ListShares().ToList();
CloudFileShare share = fileClient.GetShareReference("sinequa-data");
if (share.Exists())
{
CloudFileDirectory rootDir = share.GetRootDirectoryReference();
CloudFile file = rootDir.GetFileReference("& é #New Rich Text Document.rtf");
if (file.Exists())
{
//encode the file name
Console.WriteLine(file.Share.Uri + "/" + Uri.EscapeUriString(file.Name).Replace("&", "%26").Replace("#","%23"));
//download file
file.DownloadToFile(@"d:\des1.rtf",FileMode.OpenOrCreate);
}
}https://stackoverflow.com/questions/46302705
复制相似问题