简体   繁体   English

ASP.NET Razor Cshtml转Pdf丢失HTML格式-NonMVC

[英]ASP.NET Razor Cshtml To Pdf loses HTML formatting - NonMVC

I'm trying to publish a cshtml file to PDF but when the PDF renders all the html formatting is lost. 我正在尝试将cshtml文件发布为PDF,但是当PDF呈现所有HTML格式时,它们会丢失。 I think the problem might be that I need to render view as a string like in this example here Render View As String but I'm not using MVC and I don't understand the process well enough to determine how I can extrapolate from this example. 我认为问题可能是我需要像此处的示例一样将视图呈现为字符串渲染视图为字符串,但是我没有使用MVC,并且我对这个过程不够了解,无法确定如何从该示例中推断。 How do I get the view to render so that I don't lose the HTML formatting? 如何使视图呈现,以免丢失HTML格式?

Here's how the code is set up: 代码的设置方法如下:

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();
}

UPDATE for expected output: 更新预期输出:

Content of the cshtml: 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>

What I expect to see in the pdf is a division with a solid border, multiple lines each with a border, bolded text in some instances, and multiple inner divisions that have specific widths. 我希望在pdf文件中看到的是一个带有实线边框的分隔线,每条线都带有边框,在某些情况下为加粗文本,以及多个具有特定宽度的内部分隔线。

What I get instead is just this, no formatting: 我得到的只是这个,没有格式:

Name Date Time 名称日期时间

However, the string of html is intact when it gets to the string builder so Razor is outputting it correctly. 但是,当到达字符串构建器时html的字符串是完整的,因此Razor正确输出了它。

UPDATE - Implementation of New Page: 更新-新页面的实现:

So I found a post that talked about outputting an asp.net Panel to PDF and one person suggested that the two ways it could work was to make a new page put the content in the panel then try to print to PDF or do it as a stream on the server. 因此,我找到了一篇有关将asp.net面板输出为PDF的帖子,一个人建议它可以工作的两种方法是:创建一个新页面,将内容放入面板中,然后尝试将其打印为PDF或以PDF格式进行。服务器上的流。 So I decided to move my code to a new page so at the very least I could see on a page the output Razor generated from the cshtml page and determine if it was in fact intact which it is, all the border styles and font changes and widths/heights seem to be intact. 因此,我决定将代码移动到新页面,以便至少可以在页面上看到从cshtml页面生成的Razor输出,并确定它实际上是否完整,所有边框样式和字体更改以及宽度/高度似乎完好无损。 Then from there I tried to do a normal PDF print of the panel and still lost all formatting once I printed to PDF. 然后从那里我尝试在面板上进行常规的PDF打印,但是一旦我将其打印为PDF,仍然会丢失所有格式。 The one piece of code I've added is just a function call by the button that calls the PrintablePdf() function and on page load, I've added a line so that when content is populated it is added to the panel like so: divPrint.InnerHtml = content.Body; 我添加的代码只是通过按钮调用PrintablePdf()函数的函数,并且在页面加载时,我添加了一行,以便在填充内容时将其添加到面板中,如下所示: divPrint.InnerHtml = content.Body;

UPDATE: (no resolution) Based on the first suggestion below I changed Printable PDF to this: (Correction here I typed StringBuilder when it should have read StringReader) 更新:(无分辨率)基于以下第一个建议,我将可打印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();
}

FINAL UPDATE RESOLUTION: 最终更新解决方案:

In the end, nothing I tried using the CSHTML worked to preserve the layout in the PDf the way I needed it to. 最后,我尝试使用CSHTML进行的任何操作都无法按我需要的方式在PDf中保留布局。 I finally had to resort to dynamically creating the PDF's in codebehind using ITextSharp's PdfPTable, PdfPCell and other features to manual build the pdf. 我最终不得不求助于使用ITextSharp的PdfPTable,PdfPCell和其他功能在代码背后动态创建PDF来手动构建pdf。 I'm not thrilled with the sheer number of nested tables required to pull off the layout I needed and the code looks horrendously complex however I was able to reduce some portions to reusable method calls. 我对为实现所需的布局而需要的大量嵌套表并不感到兴奋,并且代码看起来异常复杂,但是我能够减少一些可重用方法调用的部分。

I haven't used iTextSharp before, but in the examples I've seen online, they don't use all of the many writers you have. 我以前没有使用过iTextSharp,但是在网上看到的示例中,它们并没有使用您拥有的所有作家。 I'm suspecting that one of those is stripping out the HTML. 我怀疑其中之一正在剥离HTML。

Can you try a simpler path from StringBuilder to the html parser? 您可以尝试从StringBuilder到html解析器的更简单路径吗?

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

These two pages seem to have had the same issue, but said they found a resolution. 这两页似乎有相同的问题,但表示找到了解决方法。 Their code is similar to yours except for the simplification of the StringReader. 除了简化StringReader外,它们的代码与您的代码相似。

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

ITextSharp HTML to PDF? ITextSharp HTML转换为PDF?

EDIT: It seems that the class you are using, HtmlParser, is deprecated. 编辑:似乎您正在使用的类HtmlParser被弃用。 ( http://api.itextpdf.com/itext/com/itextpdf/text/html/simpleparser/HTMLWorker.html ) The recommendation is to use XMLWorker. http://api.itextpdf.com/itext/com/itextpdf/text/html/simpleparser/HTMLWorker.html )建议使用XMLWorker。

Here is an example from http://demo.itextsupport.com/xmlworker/itextdoc/flatsite.html 这是来自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();

Also, look at this post, which talks about the special steps needed to load css, if you plan to use it. 另外,请查看这篇文章,其中讨论了如果打算使用它,则需要加载css的特殊步骤。 Replacing HTMLWorker with XML Worker in iTextSharp 在iTextSharp中用XML Worker替换HTMLWorker

 using (var srHtml = new StringReader(ConvertedString))
            {
                //Parse the HTML

                hw.Parse(srHtml);

            }

this is what worked for me user StirngReader instad of StringBuilder 这是对我有用的StringBuilder用户StirngReader instad

I've had some luck with a library called Spire PDF 我的Spire PDF库很幸运

There is a free version, just check in nuget. 有一个免费版本,只需签入nuget。 That link has instructions on how to convert an html string to a PDF. 该链接包含有关如何将html字符串转换为PDF的说明。 There is also the ability to pass it a URL and get back a PDF. 还可以向其传递URL并获取PDF。 Hope you find some use out of this. 希望您能从中找到一些用处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM