【问题标题】:URI for CloudBlockBlob is giving special characters in c#CloudBlockBlob 的 URI 在 c# 中给出了特殊字符
【发布时间】:2019-11-05 19:53:44
【问题描述】:

我有与 Azure Blob 交互的简单代码,如下所示。
我想获取上传文件的 URL。
假设如果在我的 blob 存储中,我有一个容器,其中有多个文件夹,我需要获取文件的路径。因此,我正在尝试使用 blockBlob.Uri 参数。

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.IO;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {         
            string   storageAccConnString = "Connection string";
            CloudStorageAccount storageAccount = "Account Name";
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
            string folderPath    "Folder1" + Path.DirectorySeparatorChar + "Folder2" + Path.DirectorySeparatorChar + "Folder3";
            CloudBlobContainer container = blobClient.GetContainerReference(folderPath);
            CloudBlockBlob blockBlob = container.GetBlockBlobReference("Local system filePath which needs to be uploaded to Blob");
            Console.WriteLine("URI : " + blockBlob.Uri);
            Console.WriteLine("URI : " + blockBlob.Uri.ToString());
            Console.WriteLine("URI : " + blockBlob.Uri.OriginalString);
            Console.ReadLine();  
            // I didnt write the upload code as my question was regarding URI
        }
    }
}

我收到了对此的回复,但我收到的不是“/”或“\”之类的文件夹分隔符,而是%5C

URI: https://storageaccountname.blob.core.windows.net/Folder1%5CFolder2%5Folder3/Test.zip

我该如何纠正这个问题。任何帮助都会很有用。谢谢。

【问题讨论】:

  • 这就是 URI 嵌入特殊字符的方式。它们应该在远端被很好地解码。
  • @SteveTodd ,我可以上传文件了。我没有遇到任何问题。我还必须打印 URI 以用于记录目的。而且我无法使用特殊字符获得正确的 URI。我也不想使用 String.Replace 方法。
  • @CrazyCoder 那些 是正确的 URL 字符。在任何情况下,any 云存储提供商中都没有文件夹——不是 AWS、Google 或 Azure。所有都是带有 blob 的平面容器,其名称是容器 URL 之后的字符串。在 AWS 和 Azure 中,通过处理文件夹分隔符等一些字符,模拟 Blob

标签: c# azure azure-blob-storage


【解决方案1】:

您的代码存在一些问题:

  • 首先,blob 存储有 2 级层次结构:容器和 blob。您为容器创建引用的方式不正确。由于您的容器名称包含 URL 保留字符 (\),因此它的 URL 编码为 %5C
  • 接下来,如果要在容器内的虚拟文件夹中上传文件,则需要将虚拟文件夹的路径附加到 blob 的名称中。例如,假设您有一个名为 files 的 blob 容器,并且您想上传一个名为 myfile.txt 的文件,但将其放在 Folder1/Folder2/Folder3 虚拟文件夹中,您可以这样做:
static void Main(string[] args)
{         
    string   storageAccConnString = "Connection string";
    CloudStorageAccount storageAccount = "Account Name";
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();       
    CloudBlobContainer container = blobClient.GetContainerReference('files');
    var blobName = "Folder1/Folder2/Folder3" + "myfile.txt";
    CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
    Console.WriteLine("URI : " + blockBlob.Uri);
    Console.WriteLine("URI : " + blockBlob.Uri.ToString());
    Console.WriteLine("URI : " + blockBlob.Uri.OriginalString);
    Console.ReadLine();  
    // I didnt write the upload code as my question was regarding URI
}

【讨论】:

    【解决方案2】:

    Blob 存储实际上并不使用文件夹和子文件夹。它只是使用文件路径作为完整的文件名。你所拥有的只是你的容器作为一种分离机制。 您可以上传带有文件夹分隔符的文件,但这并不会起到太大作用,即使支持 blob 存储的文件浏览器通常会模拟文件夹。 您只需在文件名中包含文件路径即可模拟文件的位置。 想要将文件移动到不同的目录?只需重命名文件路径等。

    如果需要,可以通过以下方式对 URL 进行解码:

        string input = "https://storageaccountname.blob.core.windows.net/Folder1%5CFolder2%5Folder3/Test.zip";
        string decoded = HttpUtility.UrlDecode(input);
        Console.WriteLine(decoded);
    

    【讨论】:

      【解决方案3】:

      查看您的代码,您似乎正在使用System.IO.Path.DirectorySeparatorChar(根据Microsoft docs)将:

      提供一个特定于平台的字符,用于在反映分层文件系统组织的路径字符串中分隔目录级别。

      在 Windows 系统上运行时,DirectorySeparatorChar\,而在 Linux 系统上为 /

      向 Web 服务发出请求时,用于 URI 的路径分隔符是 /,而 \ 被认为是不安全字符并需要编码 - 因此您看到的是 %5C

      要解决您面临的问题,最简单的解决方案是简单地将您对 Path.DirectorySeparatorChar 的使用替换为 "/"

      string folderPath = "Folder1/Folder2/Folder3";
      

      【讨论】:

        【解决方案4】:

        问题是您要求一个包含目录分隔符的 Container 引用。容器仅用于在根级别将 blob 组合在一起。

        容器组织一组 blob,类似于文件系统中的目录。一个存储帐户可以包含无限数量的容器,而一个容器可以存储无限数量的 Blob。

        来源:Introduction to Azure Blob storage

        Blob 中可以有目录分隔符,将它们组织在虚拟文件夹中容器内

        有关如何执行此操作的更多信息,请参阅Creating an Azure Blob Hierarchy

        【讨论】:

          【解决方案5】:

          当你像这样保存文件时,请确保:

          Stream str
          ...
          CloudBlockBlob blob = container.GetBlockBlobReference(changePathCharacters(physicalRoute) + fileName);                        
          
          blob.UploadFromStream(str);
          

          physicalRoute没有\\作为文件夹分隔符,它必须有/分隔符:

          private static string changePathCharacters(string path)
                  {
          
                      return path.Replace(@"\", @"/");
                  }
          

          然后在blockBlob.Uri.AbsoluteUri 你会得到这样的东西:

          https://storageaccountname.blob.core.windows.net/Folder1/Folder/Folder3/Test.zip

          【讨论】:

            猜你喜欢
            • 2015-01-28
            • 2013-12-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多