从 URL 返回文件作为 IActionResult [英] Return File from URL as IActionResult

查看:30
本文介绍了从 URL 返回文件作为 IActionResult的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 .Net Core 和 Razor Pages 按下按钮来下载 PDF.这和我得到的一样接近,但遇到了错误

I am attempting to get a PDF to download upon the press of a button using .Net Core and Razor Pages. This is as close as I've gotten but am encountering the error

"ObjectDisposedException:无法访问已关闭的文件.System.IO.FileStream.ReadAsync(byte[] buffer, int offset, int count,CancellationToken 取消令牌)".

"ObjectDisposedException: Cannot access a closed file. System.IO.FileStream.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)".

如何正确返回文件?

测试.cshtml

@page
@model LoanCalculator.Pages.TestModel
@{
}
<form method="post">
    <fieldset>
        <input type="submit" value="Submit" id="submitButton" />
    </fieldset>
</form>

Test.cshtml.cs

Test.cshtml.cs

namespace LoanCalculator.Pages
{
    public class TestModel : PageModel
    {

        public void OnGet()
        {
            
        }

    public async Task<IActionResult> OnPostAsync()
    {
        using var httpClient = new HttpClient();

        var url = "https://storage.googleapis.com/a2p-v2-storage/528a02ea-a399-4901-b8d6-d0494be68331";
        byte[] imageBytes = await httpClient.GetByteArrayAsync(url);

        using var fs = new FileStream("favicon.png", FileMode.Create);
        fs.Write(imageBytes, 0, imageBytes.Length);

        return File(fs, "application/pdf", "FileDownloadName.png");
    }
}

推荐答案

问题是您正在处理流而不是将流的位置设置为零.

The issue is you are disposing the stream and not setting the position of the stream to zero.

您可以通过将流从请求传递给响应来提高内存效率.

You can make this much more memory efficient by just handing the stream off from the request to the response.

看看这个例子:

var targetFile = new Uri("https://www.example.com/file.pdf");

var resp = await _httpClientFactory.CreateClient().GetAsync(
    targetFile, HttpCompletionOption.ResponseHeadersRead);

Response.ContentLength = resp.Content.Headers.ContentLength;

return File(await resp.Content.ReadAsStreamAsync(),
    "application/pdf", Path.GetFileName(targetFile.LocalPath));

(这不是从内存中测试和写入的)

此外,您应该使用 IHttpClientFactory 而不是每次都创建一个新的 HttpClient.

Also, you should be using IHttpClientFactory and not create a new HttpClient each time.

一个例子:

// ...
using System.Net.Http;
// ...

namespace LoanCalculator.Pages
{
    public class TestModel : PageModel
    {
        private readonly IHttpClientFactory _httpClientFactory;

        public TestModel(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
    }
}

在您的 Startup.cs 中,添加:

public void ConfigureServices(IServiceCollection services)
{
    // ...
    services.AddHttpClient();
    // ...
}

这篇关于从 URL 返回文件作为 IActionResult的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆