C# Azure Blob下载(GET)导致PUT请求失败
我正在从Azure blob下载文件以向我的用户显示它们。这些文件只是doc/docx/pdf格式的简历。这在几天前还可以使用,我唯一做的就是更新Azure SDK,所以这可能就是原因。 方法是从客户端调用的,最终调用如下方法: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
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也不存在,那么为什么还要进行额外的往返服务呢?