使用 PDFSharp 从 HTML 模板生成 PDF 并发送到浏览器

Posted

技术标签:

【中文标题】使用 PDFSharp 从 HTML 模板生成 PDF 并发送到浏览器【英文标题】:Generate PDF with PDFSharp from HTML template and send to browser 【发布时间】:2022-01-05 23:52:41 【问题描述】:

我目前正在为我为工作而制作的网站编写补充内容。它从 html 模板生成 PDF,然后将其提供给浏览器以便打印出来。

我创建了一个完美运行的小测试。我遇到的问题是当我编写更完整的测试时,单击生成按钮时没有任何反应。在页面加载的第一页中,PDF 被创建并显示在浏览器中。在第二页上,我什么也没得到,也没有错误消息,这使得故障排除变得如此困难。两个页面之间的代码几乎相同,所以我真的很困惑发生了什么。

我将发布我的代码的两个版本。希望你们能弄清楚发生了什么。

工作页面

<%@ Page Language="C#" %>

<!DOCTYPE html>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    
        string filePath = Server.MapPath("/test.pdf");
        string html = "<h1>Hello World</h1>";
        PdfSharp.Pdf.PdfDocument my_pdf = TheArtOfDev.HtmlRenderer.PdfSharp.PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
        my_pdf.Save(filePath);
        byte[] docStream = System.IO.File.ReadAllBytes(filePath);
        Response.ClearContent();
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "inline; filename=test.pdf");
        Response.AddHeader("Content-Length", docStream.GetLength(0).ToString());
        Response.BinaryWrite(docStream);
        Response.End();
        System.IO.File.Delete(filePath);
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
        </div>
    </form>
</body>
</html>

非工作页面

<%@ Page Language="C#" %>

<!DOCTYPE html>

<script runat="server">
    protected void Page_Load(object sender, EventArgs e)
    
        frmMain.Style.Add(HtmlTextWriterStyle.Width, "900px");
        frmMain.Style.Add(HtmlTextWriterStyle.MarginLeft, "auto");
        frmMain.Style.Add(HtmlTextWriterStyle.MarginRight, "auto");

        tblForm.Style.Add(HtmlTextWriterStyle.MarginRight, "auto");
        tblForm.Style.Add(HtmlTextWriterStyle.MarginLeft, "auto");
    
    protected void generate_pdf(object sender, EventArgs e)
    
        string html_page = System.IO.File.ReadAllText(Server.MapPath("/nice_letter.html"));
        string filePath = Server.MapPath($"/RandomString(10, true).pdf");
        html_page = html_page.Replace("letter_date", txtLetterDate.Text);
        html_page = html_page.Replace("recipient_name", txtRecipientName.Text);
        html_page = html_page.Replace("patient_name", txtPatientName.Text);
        html_page = html_page.Replace("appointment_date", txtAppointmentDate.Text);
        PdfSharp.Pdf.PdfDocument my_pdf = TheArtOfDev.HtmlRenderer.PdfSharp.PdfGenerator.GeneratePdf(html_page, PdfSharp.PageSize.Letter);
        my_pdf.Save(filePath);
        byte[] docStream = System.IO.File.ReadAllBytes(filePath);
        Response.ClearContent();
        Response.ContentType = "application/pdf";
        Response.AddHeader("Content-Disposition", "inline; filename=letter.pdf");
        Response.AddHeader("Content-Length", docStream.GetLength(0).ToString());
        Response.BinaryWrite(docStream);
        Response.End();
        System.IO.File.Delete(filePath);
    
    public string RandomString(int size, bool lowerCase = false)  
    
        Random _random = new Random();
        var builder = new StringBuilder(size);    
        char offset = lowerCase ? 'a' : 'A';  
        const int lettersOffset = 26;  
        for (var i = 0; i < size; i++)  
          
            var @char = (char)_random.Next(offset, offset + lettersOffset);  
            builder.Append(@char);  
        
        return lowerCase ? builder.ToString().ToLower() : builder.ToString();  
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="frmMain" runat="server">
        <center><h1>Nice Letter</h1></center>
        <asp:ScriptManager ID="smMain" runat="server"></asp:ScriptManager>
            <asp:UpdatePanel ID="upMain" runat="server">
                <ContentTemplate>
                    <table id="tblForm" runat="server">
                        <tr>
                            <td><asp:Label ID="lblLetterDate" Text="Letter Date: " runat="server"></asp:Label></td>
                            <td><asp:TextBox ID="txtLetterDate" Width="150" runat="server"></asp:TextBox></td>
                        </tr>
                        <tr>
                            <td><asp:Label ID="lblRecipientName" Text="Recipient: " runat="server"></asp:Label></td>
                            <td><asp:TextBox ID="txtRecipientName" Width="300" runat="server"></asp:TextBox></td>
                        </tr>
                        <tr>
                            <td><asp:Label ID="lblPatientName" Text="Patient Name: " runat="server"></asp:Label></td>
                            <td><asp:TextBox ID="txtPatientName" Width="300" runat="server"></asp:TextBox></td>
                        </tr>
                        <tr>
                            <td><asp:Label ID="lblAppointmentDate" Text="Appointment Date: " runat="server"></asp:Label></td>
                            <td><asp:TextBox ID="txtAppointmentDate" Width="150" runat="server"></asp:TextBox></td>
                        </tr>
                        <tr>
                            <td></td>
                            <td><asp:Button ID="cmdCreatePDF" runat="server" Text="Create PDF" OnClick="generate_pdf" /></td>
                        </tr>
                    </table>
                </ContentTemplate>
            </asp:UpdatePanel>
    </form>
</body>
</html>

【问题讨论】:

在浏览器中检查 f12,您正在执行 ajax 请求,您必须阅读如何捕获结果、在新窗口中打开或类似的内容。控制台中也有一些错误,但看起来 PDF 创建得很好。也许您可以将 PDF 保存到磁盘,然后返回下载链接。 @Charles 谢谢。是的,我刚刚用另一个 nuget 包进行了测试以生成 PDF,因为那个包不支持 css,我发现 ajax 正在扼杀整个事情。我不会费心去捕捉回复,我只是将信息发布到新页面并在那里创建 PDF。 【参考方案1】:

我发现了问题所在。显然这是因为我正在通过更新面板执行 ajax 请求。没有 ajax 也能正常工作。

【讨论】:

以上是关于使用 PDFSharp 从 HTML 模板生成 PDF 并发送到浏览器的主要内容,如果未能解决你的问题,请参考以下文章

使用包含在 HTML 中的外部 CSS 类的 PdfSharp 从 HTML 片段创建 PDF

无法加载文件或程序集 PDFsharp

HTML到PDF - 使用PdfSharp和HtmlRenderer分页

C# PDFSharp:如何从 PDF 中去除文本的示例?

csharp 将资源图像从嵌入式资源加载到PdfSharp / MigraDoc中

从 AngularJS 模板生成 HTML 画布