简体   繁体   English

从 URL 返回文件作为 IActionResult

[英]Return File from URL as IActionResult

I am attempting to get a PDF to download upon the press of a button using.Net Core and Razor Pages.我正在尝试使用.Net Core和Razor页面按下按钮下载PDF。 This is as close as I've gotten but am encountering the error这与我得到的一样接近,但遇到了错误

"ObjectDisposedException: Cannot access a closed file. System.IO.FileStream.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)". “ObjectDisposedException:无法访问已关闭的文件。System.IO.FileStream.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancelToken)”。

How do I properly return the file?如何正确返回文件?

Test.cshtml测试.cshtml

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

Test.cshtml.cs测试.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.问题是您正在处理 stream 而没有将 stream 的 position 设置为零。

You can make this much more memory efficient by just handing the stream off from the request to the response.您只需将 stream 从请求转移到响应,就可以提高 memory 的效率。

Take a look at this example:看看这个例子:

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));

(this is not tested and written from memory) (这不是从内存中测试和写入的)

Also, you should be using IHttpClientFactory and not create a new HttpClient each time.此外,您应该使用IHttpClientFactory而不是每次都创建一个新的HttpClient

An example of this:一个例子:

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

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

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

In your Startup.cs , add this:在您的Startup.cs中,添加以下内容:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM