【问题标题】:Azure BlobBaseClient.OpenReadAsync() leads to: System.InvalidOperationException: Response Content-Length mismatch: too few bytes written (...)Azure BlobBaseClient.OpenReadAsync() 导致:System.InvalidOperationException:响应内容长度不匹配:写入的字节太少(...)
【发布时间】:2021-10-10 12:53:53
【问题描述】:

我正在从 Azure Blob 以流的形式读取数据,并从流中创建一个文件,而不是得到 System.InvalidOperationException:响应内容长度不匹配:写入的字节太少(3696 中的 3692)。

到目前为止,我一直使用 DownloadToAsync(),一切正常,但我不得不使用 OpenReadAsync() 切换它,因为我需要在我的其他一些端点中直接反序列化来自 blob 流的数据。

这里有简单的代码:

using var blobStream = await blob.OpenReadAsync();
return File(blobStream, "application/octet-stream", "file-name");

【问题讨论】:

  • 您能否尝试升级 azure blob 存储版本,甚至尝试降级版本。或者如果您有任何想法或建议,请在此处提供您的反馈>>https://feedback.azure.com/forums/34192--general-feedback
  • 问题解决了吗?
  • 我尝试将 azure.storage.blobs 升级到 12.9.1 - 没有帮助。降级将非常复杂,因为我必须对我们的几个微服务进行更改 - 现在将继续进行。它看起来是一个错误左右(造成了一个问题) - 使用 OpenReadAsync() 时,它会在流顶部添加 4 个字节,这会导致问题。

标签: c# .net azure-blob-storage .net-5


【解决方案1】:

您的 blob 是否使用 Client-Side Encryption

在将 OpenReadAsync 返回的流传递给 File() 时,我也遇到了这个问题。 blob.OpenReadAsync() 返回加密文件的流。实际从流中读取的数据量实际上比声明的流 (.Length) 少 11 个字节,这会在 File() 中设置 Content-Length。长度的变化可能是由于在读取流时发生的解密。

using (var blobStream = await blobClient.OpenReadAsync())
{
   // blobStream.Length = 36832
   using (var fs = new FileStream("C:\\temp\\test.zip", FileMode.Create, FileAccess.Write))
   {
       await blobStream.CopyToAsync(fs);
   }
}

var fs2 = new FileStream("C:\\temp\\test.zip", FileMode.Open);
// f2.Length = 36821

传递 f2 而不是 blobClient.OpenReadAsync() 修复 File()。在传递给 File() 之前先将 blob 流写入临时位置似乎并不理想,但我不确定您还能如何获得真实的文件长度。

更新

我最初的回答只是试图说明长度问题是由加密引起的。如果您需要将 blob 流式传输回浏览器并且您正在处理大文件,那么我建议不要使用 FileResult。试试这个:

[HttpGet]
    public async Task DownloadFile()
    {         
            // these 2 lines depend on the type of file your downloading to your user. Example assumes it's a zip       
            Response.ContentType = "application/zip";
            Response.Headers[HeaderNames.ContentDisposition] = $"Content-Disposition: attachment; filename=\"whatever.zip\"";
            
            // ... get your blob from azure

            using var encryptedBlobStream = await blob.OpenReadAsync();
            // you might want to experiment with different buffer sizes
            var buffer = new byte[4096];                
            var count = 0;                
            while ((count = encryptedBlobStream.Read(buffer, 0, buffer.Length)) > 0)
            {
                await Response.Body.WriteAsync(buffer, 0, count);                    
            }                
    }

这对我有用。它应该允许您只分配一个缓冲区大小的内存来流出大文件。浏览器下载了文件并且它是未加密的。 HTTP 响应标头(从 Chrome 中看到)没有 Content-Length 但似乎无关紧要。

【讨论】:

  • 是的,我使用客户端加密。由于我正在处理大数据,您的建议对我不起作用。还是谢谢。
猜你喜欢
  • 2020-08-04
  • 2016-12-02
  • 1970-01-01
  • 1970-01-01
  • 2020-10-12
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 2019-12-15
相关资源
最近更新 更多