c# - ASP.NET Core:创建和打开 PDF(在浏览器中)
问题描述
在 ASP.NET Core 中工作并使用 iTextSharp,我正在构建 PDF 并将其保存到本地系统。我现在想在浏览器中打开该文件,但似乎无法完成这项工作,因为我在一次尝试中遇到了 FileStream 错误,而在另一次尝试中却什么也没有。
我的逻辑在下面的控制器中。我已将不必要的代码替换为// region description
. 重要的代码(我尝试过的东西)在该区TODO: Open the file
域内。
控制器
[HttpPost]
public (JsonResult, IActionResult) CreatePDF([FromBody] ReportViewModel model)
{
try
{
// region Logic code
using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream())
{
// Create the document
iTextSharp.text.Document document = new iTextSharp.text.Document();
// Place the document in the PDFWriter
iTextSharp.text.pdf.PdfWriter PDFWriter =
iTextSharp.text.pdf.PdfWriter.GetInstance(document, memoryStream);
// region Initialize Fonts
// Open the document
document.Open();
// region Add content to document
// Close the document
document.Close();
#region Create and Write the file
// Create the directory
string directory = $"{_settings.Value.ReportDirectory}\\";
System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(directory));
// region Create the fileName
// Combine the directory and the fileName
directory = System.IO.Path.Combine(directory, fileName);
// Create the file
byte[] content = memoryStream.ToArray();
using (System.IO.FileStream fs = System.IO.File.Create(directory))
{
fs.Write(content, 0, (int)content.Length);
}
#endregion
#region TODO: Open the file
// TRY: File(Stream, type) => Newtonsoft.Json.JsonSerializationException:
// Error getting value from 'ReadTimeout' on 'System.IO.FileStream'.
// ---> System.InvalidOperationException: Timeouts are supported for this stream.
System.IO.FileStream fileStream = new System.IO.FileStream(directory, System.IO.FileMode.Open);
var returnPDF = File(fileStream, contentType: "application/pdf");
// TRY: File(path, type) => Newtonsoft.Json.JsonSerializationException:
// Error getting value from 'ReadTimeout' on 'System.IO.FileStream'.
// ---> System.InvalidOperationException: Timeouts are supported for this stream.
returnPDF = File(System.IO.File.OpenRead(directory), contentType: "application/pdf" );
// TRY: File(byte[], type) => Nothing happened
returnPDF = File(content, contentType: "apllication/pdf");
#endregion
return ( Json(new { isError = false }), returnPDF );
}
}
catch (System.Exception ex)
{
Serilog.Log.Error($"ReportController.CreatePDF() - {ex}");
return ( Json(new { isError = true, errorMessage = ex.Message }), null );
}
}
参考有用的 Stackoverflow 答案
解决方案
无需从目录中再次加载文件,您只需创建一个 FileContentResult 并将已分配的 byte[] 传递给它。
return ( Json(new { isError = false }), new FileContentResult(content, "application/pdf"));
请记住,浏览器不会以这种方式下载文件。它将提取响应流但不会下载它,因为它在您的 json 响应中,因此响应内容类型将为 application/json。
相反,您可以只返回一个 IActionResult 并这样做:
return new FileContentResult(content, "application/pdf");
如果您坚持拥有“isError”信息,那么您可以另外提供一个 url 而不是 fileresult。为此,您可以在您的方法中注册IActionContextAccessor类。ConfigureServices(...)
services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
提供单独的路由并使用IUrlHelperFactory生成 url。
可以在此处找到示例。
当响应 isError 等于 false 时,可以在前端以编程方式“单击”此 url。
推荐阅读
- prometheus - 我可以将 QuestDB 用作 Promethius 存储吗?
- javascript - 如何使用 Cloudflare 工作人员进行 A/B 测试
- ios - Jmeter-iOS 应用程序录制不适用于本机应用程序
- javascript - 在中继器控件中加载更多数据
- linux - X11:改进运行时动态切换光标
- powershell - Sharepoint - Powershell 将元数据从文件夹传递到它的子文件夹和子文件夹中的文件
- javascript - 我们如何在雪花中定义输出 sys refcursor
- typescript - Typescript 无法解析声明为 webpack 别名的模块
- sql - 如果在 where 子句中我们有另一个值是什么意思
- python-3.x - ssl 安装错误 nginx 服务。错误没有这样的文件