我正在编写一个程序来从给定的 AzureStorage 帐户下载所有数据和元数据。 我几乎完成了帐户的文件部分,但在测试我的输出后,我遇到了一些奇怪的事情。
当我检查其中包含特殊字符(例如 & é #
)的文件名时,AzureStorageFile.Uri 方法返回的 Uri 与 AzureStorage Explorer 中的 Uri 不同.
一个示例是名为:& é #New Rich Text Document.rtf
该方法所需的 Uri 输出将是当我右键单击该文件并单击“属性”时 AzureStorage Explorer 给出的输出: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
属性来执行此操作,因为它的编码错误并且无法修改它的值(value)。我必须使用 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 的正确文件并进行一些更正(适用于名称中带有特殊字符的文件夹)
感谢大家的帮助
最佳答案
我使用以下代码示例从名为 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);
}
}
关于c# - AzureStorageFile.Uri 未返回具有特殊字 rune 件名的正确 Uri,导致 404 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46302705/