ASP.NET Core:创建和打开 PDF(在浏览器中)

Wou*_*rck 1 c# pdf itext asp.net-core

在 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 );
        }
    }
Run Code Online (Sandbox Code Playgroud)

参考有用的 Stackoverflow 答案

als*_*ami 6

无需从目录中再次加载文件,您只需创建一个 FileContentResult 并将字节 [] 传递给它,您已经分配了它。

return ( Json(new { isError = false }), new FileContentResult(content, "application/pdf"));
Run Code Online (Sandbox Code Playgroud)

请记住,浏览器不会以这种方式下载文件。它将提取响应流但不下载它,因为它在您的 json 响应中,因此响应内容类型将是 application/json。

您可以改为只返回一个 IActionResult 并这样做:

return new FileContentResult(content, "application/pdf");
Run Code Online (Sandbox Code Playgroud)

如果您坚持使用“isError”信息,那么您可以额外提供一个 url,而不是文件结果。为此,您可以在您的方法中注册IActionContextAccessorConfigureServices(...)

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
Run Code Online (Sandbox Code Playgroud)

提供一个单独的路由并使用IUrlHelperFactory生成一个 url。

可以在此处找到示例。

然后,当响应 isError 等于 false 时,可以在前端以编程方式“单击”此 url。