.NET:如何将Azure RetriableStreamImpl转换为ASP.Net Core IFormFile?

wvt8vs2t  于 2023-08-07  发布在  .NET
关注(0)|答案(2)|浏览(123)

我将文件以blob的形式存储在Azure存储中,每个文件一个blob。文件大小最大可达~ 100 MB。
我正在实现一个API,它将这些文件作为ASP.NetCore3.1的IFormFile接口的示例提供给使用者。
在API的服务器端实现中,我使用Azure的BlobClient.DownloadAsync()方法下载文件。这将返回一个BlobDownloadInfo示例,其中包含我需要的所有数据。具体来说,文件的内容通过BlobDownloadInfo.Value.Content属性提供,该属性在运行时包含RetriableStreamImpl的示例
我使用默认实现FileInfo类从BlobDownaldInfoMap到IFormFile,如下所示:

BlobDownloadInfo response = await blobClient.DownloadAsync();

IFormFile file = new FormFile(
    response.Value.Content, 
    0, // baseStreamOffset
    response.Value.ContentLength, 
    "foo", 
    "bar.txt")
{
    Headers = new HeaderDictionary(),
    ContentType = response.Value.ContentType,
    ContentDisposition = response.Value.Details.ContentDisposition
};

字符串
不幸的是,这段代码抛出了:

System.NotSupportedException : Specified method is not supported.
   at Azure.Core.Pipeline.RetriableStream.RetriableStreamImpl.set_Position(Int64 value)


在我看来,好像FormFile构造函数试图将流Position设置为0,但该流是一个RetriableStreamImpl,不允许设置其Position属性。
我通过将RetriableStreamImpl内容复制到MemoryStream并将其传递到FormFile构造函数来解决这个问题:

var memoryStream = new MemoryStream();
response.Value.Content.CopyTo(memoryStream);


这是一个很好的解决方案,我的问题是:这是一个很好的解决方案吗?现在是否有需要解决的性能问题?

d7v8vwbk

d7v8vwbk1#

将文件复制到内存流是个坏主意。它会减慢整个过程,如果同时发生许多下载,您将使系统内存过载。
相反,您应该尝试将流从blob存储“传递”到客户端。我们通常使用FileStreamResultblob.OpenReadAsync来实现这一点。blobClient.DownloadAsync对我来说看起来很好,所以你可以尝试用FileStreamResult替换IFile
一些代码让你开始:

var blob = container.GetBlockBlobReference(path);
var stream = blob.OpenReadAsync(cancellationToken);

// ...

// Controller action:
return new FileStreamResult(stream, contentType)
 {
     FileDownloadName = "myfile.txt" // => ContentDisposition Header
 }

字符串

thtygnil

thtygnil2#

我在阅读blob存储并将流传递给其他方法时遇到了类似的问题,这对我很有效:

var blob = container.GetBlobClient(path);
var stream = blob.OpenRead();

字符串
我返回了这个流,它是上面语句的输出。

相关问题