【问题标题】:ASP.NET Razor Cshtml To Pdf loses HTML formatting - NonMVCASP.NET Razor Cshtml To Pdf 丢失 HTML 格式 - NonMVC
【发布时间】:2015-01-15 22:07:24
【问题描述】:

我正在尝试将 cshtml 文件发布到 PDF,但是当 PDF 呈现时,所有 html 格式都丢失了。我认为问题可能是我需要将视图呈现为一个字符串,就像这个例子中的 Render View As String 一样,但我没有使用 MVC,而且我对这个过程的理解不够好,无法确定如何从这个例子中推断出来。如何让视图呈现,以免丢失 HTML 格式?

以下是代码的设置方式:

public class PrintTemplate<T> : RazorEngine.Templating.TemplateBase<T>
{
    public new T Model { get; set; }

    public PrintTemplate()
    {
        //TODO: Add Constructor Logic
    }
}

public class ViewPage
{
    public string Body { get; set; }
}

public static class PrintPDFBO
{
    public static ViewPage PrintPDF(id)
    {
        var newPrint = new ViewPage();
        var pdf = GetDataForPDF(id);
        newPrint.Body += RazorEngine.Razor.Parse(PrintPDFUtil.GetPrintTemplate(id), pdf, id.ToString());
        newPrint.Body += "</body></html>";
        return newPrint;
    }
}

protected void btnPrintPDF_OnClick(object sender, EventArgs e)
{
    var content = new ViewPage();
    content = PrintPDFBO.PrintPDF(id);
    title = DateTime.Now + "My Title";
}

UPDATE: I've tried depositing the text from my view into a panel then outputting the panel but            
        the result is the same, no formatting
protected void PrintablePdf(ViewPage view, string title)
{
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;fileName=" + title);
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
    //StringBuilder sb = new StringBuilder(view.Body);
    divPrint.InnerHtml = view.Body.ToString();
    StringWriter sw = new StringWriter(sb);
    HtmlTextWriter hw = new HtmlTextWriter(sw);
    pnlPrint.RenderControl(hw);
    StringReader sr = new StringReader(sw.ToString());
    Document pdf = new Document(PageSize.A4, 50f, 50f, 50f, 50f);
    HTMLWorker htmlparser = new HTMLWorker(pdf);
    PdfWriter.GetInstance(pdf, Response.OutputStream);
    pdf.Open();
    htmlparser.Parse(sr);
    pdf.Close();
}

更新预期输出:

cshtml的内容:

@using Print.DataType
@using Print.Data
@inherits PrintTemplate<PDFPrint>
@*Start*@
<div style="border: 1px solid black; width: 7in; height: 2in;">
  <div style="width: 3.5in; height: 2in; padding: 1em; float: left;">
    <div>
        <div style="float:left; width: 2.5in;">
            <div style="border-bottom: 1px solid black; border-right: 1px solid black; height: .3in; padding-top: .25em;">
                <span style="font-weight: bold;">OPERATOR</span>
            </div>
            <div style="border-right: 1px solid black; height: .27in;">
                <div style="vertical-align: top;">NAME OF OPERATOR</div>
                <div>@Model.Name</div>
            </div>
        </div>
        <div style="float: left; width: 1in;">
            <div style="border-bottom: 1px solid black;">
                <div style="vertical-align: top;">CARD NO.</div>
                <div>@Model.CardNo</div>
            </div>
            <div style="border-bottom: 1px solid black;">
                <div style="vertical-align: top;">DATE ISSUED</div>
                <div>@Model.IssueDate.ToShortDateString()</div>
            </div>
            <div>
                <div style="vertical-align: top;">DATE EXPIRES</div>
                <div>@Model.Expiration.ToShortDateString()</div>
            </div>
        </div>
    </div>

我希望在 pdf 中看到的是一个带有实线边框的分区、多行每行都有一个边框、在某些情况下是粗体文本以及具有特定宽度的多个内部分区。

我得到的只是这个,没有格式:

名称 日期 时间

但是,html 的字符串在到达字符串生成器时是完整的,因此 Razor 可以正确输出它。

更新 - 新页面的实现:

所以我发现一篇关于将 asp.net 面板输出到 PDF 的帖子,有人建议它可以工作的两种方法是创建一个新页面,将内容放在面板中,然后尝试打印到 PDF 或执行它作为服务器上的流。所以我决定将我的代码移动到一个新页面,这样至少我可以在一个页面上看到从 cshtml 页面生成的输出 Razor 并确定它是否实际上是完整的,所有的边框样式和字体都发生了变化和宽度/高度似乎完好无损。然后从那里我尝试对面板进行正常的 PDF 打印,但在打印为 PDF 后仍然丢失了所有格式。我添加的一段代码只是调用 PrintablePdf() 函数的按钮的函数调用,在页面加载时,我添加了一行,以便在填充内容时将其添加到面板中,如下所示: divPrint.InnerHtml = content.Body;

更新:(无分辨率) 根据下面的第一个建议,我将 Printable PDF 更改为: (更正这里我在应该读取 StringReader 时键入了 StringBuilder)

protected void PrintablePdf(string title, string body)
{
    Response.Clear();
    Response.Buffer = true;
    Response.ContentType = "application/pdf";
    Response.AddHeader("content-disposition", "attachment;fileName=" + title);
    Response.Cache.SetCacheability(HttpCacheability.NoCache);

    Document pdf = new Document(PageSize.A4, 50f, 50f, 50f, 50f);
    HTMLWorker htmlparser = new HTMLWorker(pdf);
    PdfWriter.GetInstance(pdf, Response.OutputStream);
    pdf.Open();
    htmlparser.Parse(new StringReader(body));
    pdf.Close();
}

最终更新解决方案:

最后,我没有尝试使用 CSHTML 以按照我需要的方式保留 PDf 中的布局。我最终不得不求助于使用 ITextSharp 的 PdfPTable、PdfPCell 和其他功能在代码隐藏中动态创建 PDF 来手动构建 pdf。我对完成所需布局所需的大量嵌套表并不感到兴奋,而且代码看起来非常复杂,但是我能够将一些部分减少为可重用的方法调用。

【问题讨论】:

  • “html 格式”是什么意思? Razor.Parse 将根据您传递给它的模板的内容返回一个 HTML 格式的字符串。什么是它不会错误地提供输入和实际输出与预期输出。
  • 我已更新信息以包含 cshtml 和预期输出,谢谢。
  • 您使用哪个库来生成 PDF?
  • 我在页面上使用 iTextSharp.text、iTextSharp.html 和 iTextSharp.pdf。

标签: c# asp.net razor


【解决方案1】:

我以前没有使用过 iTextSharp,但是在我在网上看到的示例中,它们并没有使用您拥有的所有编写器。我怀疑其中之一正在剥离 HTML。

您可以尝试从 StringBuilder 到 html 解析器的更简单路径吗?

htmlparser.Parse(new StringReader(sb.ToString()));

这两个页​​面似乎有同样的问题,但说他们找到了解决办法。除了简化 StringReader 之外,他们的代码与您的代码相似。

http://forums.asp.net/t/1970922.aspx?iTextSharp+PDF+formatting+problems+from+HTML+tags

ITextSharp HTML to PDF?

编辑:您使用的类 HtmlParser 似乎已被弃用。 (http://api.itextpdf.com/itext/com/itextpdf/text/html/simpleparser/HTMLWorker.html) 推荐使用 XMLWorker。

这是来自http://demo.itextsupport.com/xmlworker/itextdoc/flatsite.html的示例

Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
    new FileOutputStream("results/loremipsum.pdf"));
document.open();
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
    new FileInputStream("/html/loremipsum.html"));
document.close();

另外,如果您打算使用它,请查看这篇文章,其中讨论了加载 css 所需的特殊步骤。 Replacing HTMLWorker with XML Worker in iTextSharp

【讨论】:

  • 我确实尝试了这里的建议;但是,结果是一样的,我得到了数据但没有格式化。查看我如何更改它的更新示例。
  • 很抱歉问了一个明显的问题,但是在您更新的 PrintablePdf 中,您是否确认 body 参数包含 HTML 标记?你能传入一个更简单的 html 简介,看看是否也能去掉它吗?
  • 所以我确实看了,并且 body 参数只有以
    标记开头和结尾的 html,无论我将它作为字符串直接传递给解析器还是将它传递给 asp 面板然后呈现了这一点。所以我尝试将它添加到 body 参数,所以它的格式如下:“
    ...
    ”但结果仍然相同。跨度>
【解决方案2】:
 using (var srHtml = new StringReader(ConvertedString))
            {
                //Parse the HTML

                hw.Parse(srHtml);

            }

这对我有用,用户 StirngReader instad of StringBuilder

【讨论】:

  • 我已经解析了文本并使用了字符串阅读器,但格式仍然丢失,谢谢。
【解决方案3】:

我在一个名为 Spire PDF 的库上遇到了一些运气

有一个免费版本,只需签入nuget。该链接包含有关如何将 html 字符串转换为 PDF 的说明。还可以将 URL 传递给它并取回 PDF。希望你能从中找到一些用处。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2019-12-29
    相关资源
    最近更新 更多