【问题标题】:shareSasBuilder doesn't work when filename has special characters当文件名包含特殊字符时,shareSasBuilder 不起作用
【发布时间】:2021-01-08 21:12:52
【问题描述】:

我需要允许用户下载存储在 Azure 文件共享中的特定文件。只要文件名不包含特殊字符,它就可以正常工作,但如果它包含任何特殊字符(例如空格),则会失败并出现 AuthenticationFailed 错误。

<Error>
<Code>AuthenticationFailed</Code>
<Message>
Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. RequestId:19654741-801a-0014-1b04-9197c9000000 Time:2020-09-22T17:20:44.1980779Z
</Message>
<AuthenticationErrorDetail>
Signature did not match. String to sign used was r 2020-09-22T19:20:42Z /file/depotsracq/cegep/BA/ZOOM 2.pdf 2019-07-07
</AuthenticationErrorDetail>
</Error>

这是返回 Uri 的方法。我很确定它与特殊字符的编码有关。在 ShareSasBuilder 中,我传递了不带编码的文件名 (file.Path),但 URL 需要对特殊字符进行编码。我猜 Azure 期望特殊字符的编码方式不同。

    public Uri getFileUri(string filePath)
    {
        ShareDirectoryClient directory = shareClient.GetDirectoryClient(Path.GetDirectoryName(filePath));
        ShareFileClient file = directory.GetFileClient(Path.GetFileName(filePath));

        if (file.Exists())
        {
            var shareSasBuilder = new ShareSasBuilder
            {
                ShareName = directory.ShareName,
                FilePath = file.Path,
                ExpiresOn = DateTime.UtcNow.AddHours(+2)
            };

            shareSasBuilder.SetPermissions(ShareFileSasPermissions.Read);

            SasQueryParameters sasQueryParameters = shareSasBuilder.ToSasQueryParameters(sharedKeyCredential);

            UriBuilder fullUri = new UriBuilder(file.Uri)
            { 
                 Query = sasQueryParameters.ToString()
            };

            return fullUri.Uri;
        }
        else
        {
            return null;
        }
    }

【问题讨论】:

  • 如果我注释掉“FilePath = file.Path”这一行,它可以正常工作。证明它与文件名有关。但是,我需要将权限限制为特定文件。

标签: azure azure-storage azure-storage-files


【解决方案1】:

请确保您使用的是最新版本的 azure 文件共享包:Azure.Storage.Files.Shares, version 12.4.0

我在我身边测试了它,文件名包含特殊字符,如white-space@ 等。它返回一个带有 sastoken 的有效 url,它可用于成功访问文件。示例代码如下:

       string conn_str = "DefaultEndpointsProtocol=https;AccountName=xxx;AccountKey=xx;EndpointSuffix=core.windows.net";
        
        var sharedKeyCredential = new StorageSharedKeyCredential("xxx", "xxx");

        ShareServiceClient client = new ShareServiceClient(conn_str);
        var shareClient = client.GetShareClient("aaa");

        ShareDirectoryClient directory = shareClient.GetDirectoryClient("bbb");

        //use file name contains special chars like @
        ShareFileClient file = directory.GetFileClient("foo@@.txt");

        //or use the file name contains white-space
        //ShareFileClient file = directory.GetFileClient("foo test.txt");

        if (file.Exists())
        {
            var shareSasBuilder = new ShareSasBuilder
            {
                ShareName = directory.ShareName,
                FilePath = file.Path,
                ExpiresOn = DateTime.UtcNow.AddHours(+2)
            };

            shareSasBuilder.SetPermissions(ShareFileSasPermissions.Read);

            SasQueryParameters sasQueryParameters = shareSasBuilder.ToSasQueryParameters(sharedKeyCredential);

            UriBuilder fullUri = new UriBuilder(file.Uri)
            {
                Query = sasQueryParameters.ToString()
            };

            return fullUri.Uri;
        }

如果您仍有任何问题,请告诉我。

【讨论】:

  • 有效!我从 12.2.1 升级到 12.4.0,它解决了这个问题。非常感谢!
猜你喜欢
  • 2021-10-15
  • 2017-12-02
  • 1970-01-01
  • 2016-01-01
  • 2013-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-30
相关资源
最近更新 更多