.NET Core 3 MVC 从 HTTP 下载文件并使用最小内存重新传递给客户端

Fir*_*ion 2 c# asp.net-core-mvc .net-core

我有一个 .NET Core 3 MVC 应用程序,需要通过 HTTP 从一个位置读取文件,然后将其重新传递回响应。其中一些文件的大小约为 200MB。

File我所拥有的有效,但它在将结果发送给客户端之前将整个文件读取到内存中。有没有一种方法可以使其本质上成为一个直通,其中读取流流入响应流,以便服务器上需要很少的内存?

这是我现在所拥有的,但我认为对于大文件来说效果不佳:

if (requestedFile != null)
{
    using (var client = new System.Net.Http.HttpClient())
    {
        using (var result = await client.GetAsync(requestedFile.DownloadUrl))
        {
            if (result.IsSuccessStatusCode)
            {
                var bytes = await result.Content.ReadAsByteArrayAsync();
                return File(bytes, "application/zip", "largefile.zip");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我也尝试过这会导致“无法访问关闭的流”的运行时错误:

using (var client = new System.Net.Http.HttpClient())
{
    using (var httpResponseMessage = await client.GetAsync(requestedFile.DownloadUrl))
    {
        return File(await httpResponseMessage.Content.ReadAsStreamAsync(), "application/zip", "largefile.zip");

    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

经过一番尝试和错误后的解决方案是删除所有 using 语句并让其FileStreamResult自行关闭流。所以我最终得到:

var client = new HttpClient();
var result = await client.GetAsync(requestedFile.DownloadUrl);
var stream = await result.Content.ReadAsStreamAsync();
return new FileStreamResult(stream, "application/zip")
{
    FileDownloadName = "largefile.zip"
};
Run Code Online (Sandbox Code Playgroud)

jle*_*jle 6

文件的重载之一是流。只需将该 URL 作为 Stream 获取或将响应正文作为流读取并立即在重载中返回:

var client = new System.Net.Http.HttpClient();
  
var result = await client.GetAsync(requestedFile.DownloadUrl);
var stream = await result.Content.ReadAsStreamAsync();
 
return File(stream,"application/pdf", "Invoice.pdf");
Run Code Online (Sandbox Code Playgroud)

注意:如果将 Stream 包装在 using 块中,则会失败,因为 FileResult 已经关闭了 Stream。