问题描述
我想从 Azure 下载存储 blob,并通过 .NET Web 应用程序将其流式传输到客户端。 Blob 已正确上传,并且在我的 Azure 存储帐户中可见。
令人惊讶的是,以下内容在 HttpBaseStream 中引发异常:
[...]
var blobClient = _containerClient.GetBlobClient(Path.Combine(fileName));
var stream = await blobClient.OpenReadAsync();
return stream;
-> 当我进一步返回文件 (return File(stream,MediaTypeNames.Application.Octet);
) 时,下载按预期工作。
我尝试将流推送到 MemoryStream 中,但它也因相同的异常而失败:
[...]
var blobClient = _containerClient.GetBlobClient(Path.Combine(fileName));
var stream = new MemoryStream();
await blobClient.DownloadToAsync(stream);
return stream
->当我更进一步时,返回文件会导致超时。
我该如何解决?为什么会出现此异常 - 我遵循了 Microsoft 的官方快速入门指南。
解决方法
以下在 HttpBaseStream 中抛出异常
看起来 HTTP 结果类型正在尝试设置 for (const patientId of patientIds)
{
console.log("PATIENT ID:" + patientId)
describe('GET API',function () {
it('Login Request',async function () {
let response= await util.apiCall(patientId)
.then(function(response){
console.log("Checking bad request:" + response.badRequest);
console.log("Checking status code:" + response.status)
})
})
标头并且正在读取 Content-Length
以执行此操作。那将是很自然的事情。但是,处理 Length
而根本不设置 NotSupportedException
也是很自然的。
如果 Content-Length
仅在调试器中运行时出现,则忽略它。
如果异常实际上是抛出到您的代码中(即导致请求失败),那么您需要遵循本答案的其余部分。
首先,创建一个最小的可重现示例并向 .NET 团队报告错误。
为了同时解决这个问题,我建议编写一个流包装器来返回一个已经确定的长度,你可以从 Azure blob 属性中获取该长度。例如:
NotSupportedException
这应该足以让您的应用正常工作。
我试图将流推入 MemoryStream
这不起作用,因为您需要在某个时候“倒带”public sealed class KnownLengthStreamWrapper : Stream
{
private readonly Stream _stream;
public KnownLengthStreamWrapper(Stream stream,long length)
{
_stream = stream;
Length = length;
}
public override long Length { get; private set; }
... // override all other Stream members and forward to _stream.
}
,例如:
MemoryStream
,
检查我已经在 git 上发布的所有 blob 选项的示例,这些选项按预期工作。 Reference
public void DownloadBlob(string path)
{
storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
CloudBlobClient client = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = client.GetContainerReference("images");
CloudBlockBlob blockBlob = container.GetBlockBlobReference(Path.GetFileName(path));
using (MemoryStream ms = new MemoryStream())
{
blockBlob.DownloadToStream(ms);
HttpContext.Current.Response.ContentType = blockBlob.Properties.ContentType.ToString();
HttpContext.Current.Response.AddHeader("Content-Disposition","Attachment; filename=" + Path.GetFileName(path).ToString());
HttpContext.Current.Response.AddHeader("Content-Length",blockBlob.Properties.Length.ToString());
HttpContext.Current.Response.BinaryWrite(ms.ToArray());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Close();
}
}