我们正在应用程序中实现一个文件存储,我们将所有文件存储在Azure Blob存储中的私有容器中.我们有一个虚拟文件夹系统,我们在Blob存储中复制它.

例如,假设我为Company A工作,我将file_1.txt上传到Folder #1,它将驻留在Blob存储中的/vault/Company A/Folder #1/file_1.txt中.

我们使用以下代码生成SAS令牌:

public  static Uri GetServiceSasUriForCloudBlockBlob(CloudBlockBlob cloudBlockBlob, string permissions = "r")
{
            
    var sasBuilder = new SharedAccessBlobPolicy()
    {
        SharedAccessStartTime = DateTimeOffset.UtcNow.AddMinutes(-5),
        SharedAccessExpiryTime = DateTimeOffset.UtcNow.AddMinutes(5),
        Permissions = SharedAccessBlobPolicy.PermissionsFromString(permissions)
    };
            
    var sasUri = cloudBlockBlob.GetSharedAccessSignature(sasBuilder);

    return new Uri(cloudBlockBlob.Uri + sasUri);

}

然而,这不起作用.我们得到的错误是:

<Error>
    <script type="text/javascript"/>
    <Code>AuthenticationFailed</Code>
    <Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:f82118d1-101e-002a-1381-97ac16000000 Time:2022-07-14T12:55:34.6370028Z</Message>
    <AuthenticationErrorDetail>Signature did not match. String to sign used was r 2022-07-14T12:50:27Z 2022-07-14T13:00:27Z /blob/[blobname]/vault/Company A/Folder #1/file_1.txt 2019-07-07 b </AuthenticationErrorDetail>
</Error>

从Azure门户或Azure Storage Explorer生成SAS令牌时,没有问题

Blob中文件路径中的特殊字符似乎有问题.因此,我们try 手动转义所有空格和特殊字符以解决此问题,但在执行此操作时,CloudBlockBlob会再次对其进行编码(例如:转义My%20File.txtMy%2520File.txt).

目前我们使用的唯一操作是在对象上读取,但这可能会在将来扩展.

我们可以禁止在文件夹/文件中使用空格和特殊字符,但这并不是解决问题,而是解决问题.在不实施命名策略的情况下,我们如何解决这个问题?

事实证明,这是一个设计问题,虽然SDK文档从未明确禁止使用未替换的blob路径,但它确实不允许容器名称使用字母数字和破折号以外的任何名称.

推荐答案

对于任何有相同问题的人(无论是在SDK版本11还是12上),我强烈建议不要使用空格/特殊字符,而不进行部分编码,

var fileName = "file.txt"

// Note that the order here matters
var folderNames = ["Folder #1", "Folder #1.1"]

// becomes: Folder+%25231/Folder+%25231.1
var encodedPath = folderNames.Select(WebUtility.UrlEncode).Aggregate((x, y) => x + "/" + y);

// becomes: Folder+%25231/Folder+%25231.1/file.txt
var blobPath = ${encodedPath}/{fileName}"

这在Azure Storage Explorer中看起来更糟糕,但这确实避免了以编程方式编码字符串的问题

Csharp相关问答推荐

当打印一行x个项目时,如何打印最后一行项目?

如何创建ASP.NET Core主机并在同一进程中运行请求

在多对多关系上不删除实体

不仅仅是一个简单的自定义按钮

如何使用XmlSerializer反序列化字符串数组?

为什么总输出就像12.3没有一分一样?

Unity中的刚体2D运动

可为空的泛型属性

发布用于Linux Ubuntu的C#应用程序

如何在C#中转换泛型包装类内部的派生类

委托RequestDelegate不带2个参数-ASP.NET Core 8最小API

同一组件的多个实例触发相同的事件处理程序

当try 测试具有协变返回类型的抽象属性时,类似功能引发System.ArgumentException

如何在mediatr命令中访问HttpContext而不安装弃用的nuget包

C#LINQ延迟执行和嵌套方法

是否可以从IQueryable T中获取一个IdentyEntry T>

如何在Xamarin.Forms中检索PanGesture事件的位置?

使用SQL Server 2022+时,我是否必须将代码从SqlConnection类对象中迁移出来?

为什么C#中的类型别名不能在另一个别名中使用?

能否将我图表中的星号与X轴上一天中的第二位数字对齐?