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

时间:2014-11-18 16:23:57

标签: c# asp.net razor

我正在尝试将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更改为: (在此更正我输入StringBuilder时应该读取StringReader)

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。我不满足于拉出我需要的布局所需的大量嵌套表,并且代码看起来非常复杂,但是我能够将一些部分减少到可重用的方法调用。

3 个答案:

答案 0 :(得分:0)

之前我没有使用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

答案 1 :(得分:0)

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

                hw.Parse(srHtml);

            }

这对我使用StringReader而不是StringBuilder

起作用了

答案 2 :(得分:-1)

我对一个名为Spire PDF

的图书馆运气不错

有一个免费版本,只需检查nuget。该链接提供了有关如何将html字符串转换为PDF的说明。还可以传递URL并获取PDF。希望你能找到一些用途。