Return 来自 URL 的文件作为 IActionResult
Return File from URL as IActionResult
我正在尝试使用 .Net Core 和 Razor Pages 按下按钮下载 PDF。这和我得到的一样接近,但我遇到了错误
"ObjectDisposedException: Cannot access a closed file.
System.IO.FileStream.ReadAsync(byte[] buffer, int offset, int count,
CancellationToken cancellationToken)".
如何正确return文件?
Test.cshtml
@page
@model LoanCalculator.Pages.TestModel
@{
}
<form method="post">
<fieldset>
<input type="submit" value="Submit" id="submitButton" />
</fieldset>
</form>
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");
}
}
问题是您正在处理流而不是将流的位置设置为零。
您可以通过将流从请求移交给响应来提高内存效率。
看看这个例子:
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
。
这方面的一个例子:
// ...
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();
// ...
}
我正在尝试使用 .Net Core 和 Razor Pages 按下按钮下载 PDF。这和我得到的一样接近,但我遇到了错误
"ObjectDisposedException: Cannot access a closed file. System.IO.FileStream.ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)".
如何正确return文件?
Test.cshtml
@page
@model LoanCalculator.Pages.TestModel
@{
}
<form method="post">
<fieldset>
<input type="submit" value="Submit" id="submitButton" />
</fieldset>
</form>
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");
}
}
问题是您正在处理流而不是将流的位置设置为零。
您可以通过将流从请求移交给响应来提高内存效率。
看看这个例子:
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
。
这方面的一个例子:
// ...
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();
// ...
}