C# Azure Blob下载(GET)导致PUT请求失败

C# Azure Blob下载(GET)导致PUT请求失败,c#,azure,dependencies,azure-storage-blobs,C#,Azure,Dependencies,Azure Storage Blobs,我正在从Azure blob下载文件以向我的用户显示它们。这些文件只是doc/docx/pdf格式的简历。这在几天前还可以使用,我唯一做的就是更新Azure SDK,所以这可能就是原因。 方法是从客户端调用的,最终调用如下方法: CloudBlobContainer container = GetContainer(containerName); CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName); block

我正在从Azure blob下载文件以向我的用户显示它们。这些文件只是doc/docx/pdf格式的简历。这在几天前还可以使用,我唯一做的就是更新Azure SDK,所以这可能就是原因。 方法是从客户端调用的,最终调用如下方法:

CloudBlobContainer container = GetContainer(containerName);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
blockBlob.Properties.ContentType = contentType;

using (var fileStream = new MemoryStream())
{
    await blockBlob.DownloadToStreamAsync(fileStream);
    return fileStream;
}
GetContainer方法定义如下:

try
{
    var storageAccount = StorageAccount;
    var blobClient = storageAccount.CreateCloudBlobClient();
    var container = blobClient.GetContainerReference(containerName);

    if (container.CreateIfNotExists())
    {
        container.SetPermissions(new BlobContainerPermissions
        {
             PublicAccess = BlobContainerPublicAccessType.Blob
        });
    }
    return container;
}
catch (Exception e)
{
    Logger.Error("GetBlobContainer fail", e);
}
截至昨天,我一直在Azure Application Insights中看到失败的依赖项调用。不是错误,只是失败的依赖项。每次下载文件时,都会执行GET请求,但同时由于某种原因也会执行PUT请求,并且失败。 在下图中,您可以看到此错误的洞察日志。每个看起来都一样。调用方法,下载文件,然后调用PUT请求


为什么要创建这个PUT请求,以及如何解决这个行为,这让我抓狂。另一个有趣的是,据我所知,一切正常,我对blob的所有上传和下载调用都会发生这种情况。

PUT请求是由container.CreateIfNotExists()触发的,当您的容器已经存在时,它应该会按预期失败。整个代码路径工作正常,我认为您无需担心任何事情

container.CreateIfNotExists()的机制是Azure存储客户端库将向服务器发送一个Put容器请求,如果是409(冲突),则会吞掉该错误,因为它表示容器已经存在。

如8.0.0版的关于中所述:

CreateIfNotExists方法现在只执行一个REST调用,而不是两个

这是我的测试,您可以参考它以更好地了解这一变化:

在版本8.0.0之前,
CreateIfNotExists
将检查目标是否存在,如果不存在,则创建资源,如下所示:

try
{
    var storageAccount = StorageAccount;
    var blobClient = storageAccount.CreateCloudBlobClient();
    var container = blobClient.GetContainerReference(containerName);

    if (container.CreateIfNotExists())
    {
        container.SetPermissions(new BlobContainerPermissions
        {
             PublicAccess = BlobContainerPublicAccessType.Blob
        });
    }
    return container;
}
catch (Exception e)
{
    Logger.Error("GetBlobContainer fail", e);
}

而在此版本8.0.0之后,
CreateIfNotExists
将直接调用create方法,并使用
try catch
包装此操作以捕获异常

总之,此问题是由于Microsoft Azure Storage Libraries for.NET在特定版本下的更改所致。您可以调用
CloudBlobContainer.Exist()
,然后调用
CloudBlobContainer.Create()
,而不是
CloudBlobContainer.CreateIfNotExists
。但此时,您需要使用
try catch
包装
CloudBlobContainer.Create()
,以自己捕获异常(例如,有人创建了同名资源等)


此外,您还可以利用或检索有关
CloudBlobContainer.CreateIfNotExists

的更详细的实现,为什么要返回已处理的
文件流?这不会引起问题吗?你用那个值做什么?我返回它并用ToArray()方法从中读取字节数组。字节数组在关闭/处理流后仍然可用()谢谢Bruce,这回答了我的问题。我只是不喜欢在控制台中看到大量错误,所以我想我会将代码更改为单独的调用。不需要try/catch。如果Exists()返回false,则调用CreateIfNotExists()。但也要考虑避免完全调用。如果容器不存在,那么blob也不存在,那么为什么还要进行额外的往返服务呢?