如何使用 SAS 令牌在 C# API 的容器中列出 Blob

How to List Blobs in a Container iwth C# API using a SAS token

我正在使用 SAS 令牌通过 c# API 访问 Azure Blob Store。我可以在容器中成功创建新的 blob,并且根据 blob 的名称,我可以读取该 blob 并获取其内容。但是,我无法列出容器中的 blob,因为我收到 InvalidURl 错误:请求的 URI 不代表服务器上的任何资源。

我对所有三个请求(上传、下载和列表)使用相同的 sas URI。

我使用以下代码生成 sas URI:

if (containerClient.CanGenerateSasUri)
{
     BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = containerClient.Name,
        Resource = "c"
    };

    if (storedPolicyName == null)
    {
        sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
        sasBuilder.SetPermissions(BlobContainerSasPermissions.All);
    }
    else
    {
        sasBuilder.Identifier = storedPolicyName;
    }

    Uri sasUri = containerClient.GenerateSasUri(sasBuilder);
}

我尝试使用以下代码列出 blob 的名称:

    var serviceClient = new BlobServiceClient(sasUri);
    var containerClient = serviceClient.GetBlobContainerClient(container);
    var blobs = containerClient.GetBlobsByHierarchyAsync();

    await foreach (var blob in blobs)
    {
        if (blob.IsBlob)
        {
            blobNames.Add(blob.Blob.Name);
        }           
    }

如果我使用连接字符串(而不是 sas URI)创建 BlobServiceClient,则此代码可以工作并且可以列出我使用 sas URI 上传的 blob,但是使用 sas URI 失败并显示 InvalidURL(甚至虽然是我刚刚用于在容器中创建 blob 的同一个 sas 令牌,并且它有权列出容器中的 blob)。

如果我对已知文件名进行硬编码,我可以使用 sas containerClient 创建一个有效的 BlobClient:

    var blobClient = containerClient.GetBlobClient("blobname");
    if (await blobClient.ExistsAsync())
    {
        var stream = await blobClient.DownloadStreamingAsync();
        return stream.Value.Content;
    }

我需要做什么才能使 List 操作与 sas 令牌一起使用?非常感谢任何指向我所缺少的东西的指针!

您 运行 遇到问题的原因是因为您使用 Blob 容器 SAS URI 创建 BlobServiceClient 并且当您使用服务客户端创建 BlobContainerClient 实例时,容器名称重复两次。

可能的解决方案:

  1. 使用容器 SAS URL 直接创建 BlobContainerClient 的实例。你可以这样做:
containerClient = new BlobContainerClient(sasUri);
  1. 仅使用 SAS 令牌(而不是 SAS URL)和帐户端点创建 BlobServiceClient 的实例。你可以这样做:
var endpoint = $"{uri.Scheme}://{uri.Host}";
var sasToken = uri.Query;
var credentials = new AzureSasCredential(sasToken);
var serviceClient = new BlobServiceClient(new Uri(endpoint), credentials);
var containerClient = serviceClient.GetBlobContainerClient(container);
...
...rest of your code
...