我们的网站业务会生成一个报告,用网页展示出来,要有生成pdf并下载的功能,关键是生成pdf。

用内容一段段去拼pdf,想想就很崩溃,所以就去网上找直接把html生成pdf的方法。

网上资料大部分都是用的iTextSharp的XMLWorkerHelper做的(代码我贴在后面),遇到的问题是,它对css样式的支持比较古老或者说简单,所以重新改了一下我的html样式,div大部分都换成了table等,搞定后运行了一段时间没出什么问题。

但是,最近发现它有一种情况会报错。我的html内容是一个订单,包含多个小项,每个小项有自己的内容。最近发现如果小项的内容稍多,比如几千个字符,生成pdf时在分页那儿会陷入死循环。

由于我的小项一直被当成一整块,如果一页剩下的地方显示不完,它会整个挪到下一页,不会从中间截断,所以我猜测,如果被它判定一段内容是不能分割的,而内容的长度就已经超出了一整页的长度,就会出错。

我试图调整自己的内容的格式等等,让它不被判定为不可分割,没有成功,而且没有看到源码,最后没有解决问题,只好找另外的方式生成pdf。

第二次映入眼帘的是wkhtmltopdf,同时有人提到了Pechkin,是作者在wkhtmltopdf基础上开发的,更方便.NET开放使用,不过原版有个bug,有网友给出了修正版本。

这个的使用更简单,不过比较奇葩的是,需要把几个dll库放到根目录。

这一次接入完成后没有出现内容长了就挂掉的情况,但是也有个毛病:

它的分页非常“硬”,有可能会把一行字从中间拦腰截断,分在上下两页。

两害相权取其轻,只能先用着了。

如果能确定内容不会太长,还是iTextSharp比较好。

下面是两种方式的使用代码:

iTextSharp:

 public class PDFHelper
{
public byte[] ConvertHtmlTextToPDF(string htmlText)
{
if (string.IsNullOrEmpty(htmlText))
{
return null;
}
//避免当htmlText无任何html tag标签的纯文字时,转PDF时会挂掉,所以一律加上<p>标签
htmlText = "<p>" + htmlText + "</p>";
MemoryStream outputStream = new MemoryStream();//要把PDF写到哪个串流
byte[] data = Encoding.UTF8.GetBytes(htmlText);//字串转成byte[]
MemoryStream msInput = new MemoryStream(data);
Document doc = new Document();//要写PDF的文件,建构子没填的话预设直式A4 PdfWriter writer = PdfWriter.GetInstance(doc, outputStream);
PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, , doc.PageSize.Height, 1f);
//开启Document文件
doc.Open();
HeaderAndFooterEvent header = new HeaderAndFooterEvent();
header.tpl = writer.DirectContent.CreateTemplate(, );
writer.PageEvent = header; //使用XMLWorkerHelper把Html parse到PDF档里
XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msInput, null, Encoding.UTF8, new UnicodeFontFactory()); //将pdfDest设定的资料写到PDF档
PdfAction action = PdfAction.GotoLocalPage(, pdfDest, writer);
writer.SetOpenAction(action);
doc.Close();
msInput.Close();
outputStream.Close();
//回传PDF档案
return outputStream.ToArray(); }
}
public class UnicodeFontFactory : FontFactoryImp
{ public override Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color, bool cached)
{
string FontPath = System.Web.Hosting.HostingEnvironment.MapPath("~/Font/"); BaseFont bfYaHei = BaseFont.CreateFont(FontPath + "msyh.ttc,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
return new Font(bfYaHei, size, style, color);
}
} public class HeaderAndFooterEvent : PdfPageEventHelper, IPdfPageEvent
{
public PdfTemplate tpl = null;
public bool PAGE_NUMBER = true;
private int PageCount = ;
private static string FontPath = System.Web.Hosting.HostingEnvironment.MapPath("~/Font/");
private static BaseFont bfYaHei = BaseFont.CreateFont(FontPath + "msyh.ttc,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
private static iTextSharp.text.Font font = new Font(bfYaHei, , Font.NORMAL, BaseColor.BLACK); //重写 关闭一个页面时
public override void OnEndPage(PdfWriter writer, Document document)
{
if (PAGE_NUMBER)
{
Phrase footer = new Phrase("www.XXXX.com 第" + writer.PageNumber + "页/共 页", font);
PdfContentByte cb = writer.DirectContent; //模版 显示总共页数
cb.AddTemplate(tpl, document.Right - + document.LeftMargin, document.Bottom - );//调节模版显示的位置 //页脚显示的位置
ColumnText.ShowTextAligned(cb, Element.ALIGN_CENTER, footer, document.Right - + document.LeftMargin, document.Bottom - , );
}
}
//重写 打开一个新页面时
public override void OnStartPage(PdfWriter writer, Document document)
{
if (PAGE_NUMBER)
{
PageCount += ;
writer.PageCount = PageCount;
}
}
//关闭PDF文档时
public override void OnCloseDocument(PdfWriter writer, Document document)
{
tpl.BeginText();
tpl.SetFontAndSize(bfYaHei, );//生成的模版的字体、颜色
tpl.ShowText(PageCount.ToString());//模版显示的内容
tpl.EndText();
tpl.ClosePath();
}
//定义输出文本
public static Paragraph InsertTitleContent(string text)
{ Paragraph paragraph = new Paragraph(text, font);//新建一行 paragraph.Alignment = Element.ALIGN_CENTER;//居中 paragraph.SpacingBefore = ; paragraph.SpacingAfter = ;
paragraph.SetLeading(, );//每行间的间隔
return paragraph;
}
}

Pechkin:

 public static byte[] ConvertHtmlToPdf(string html)
{ try
{
using (IPechkin pechkin = Factory.Create(new GlobalConfig()))
{
ObjectConfig oc = new ObjectConfig();
oc.SetPrintBackground(true)
.SetLoadImages(true).Footer.SetContentSpacing().SetLeftText("www.XXXX.com").SetRightText("[page]/[toPage]");
byte[] pdf = pechkin.Convert(oc, html);
return pdf;
}
}
catch (Exception)
{ }
return null;
}

大家有更好的解决方式,希望赐教。

C# html生成PDF遇到的问题,从iTextSharp到wkhtmltopdf的更多相关文章

  1. C#生成PDF总结

    (一)C#生成PDF总结 (1)iTextSharp控件对iTextSharp研究还可以表格.文字.各种GDI对象,图片,水印,文字旋转(2)aspose的控件(3)PDF Library这个类库(只 ...

  2. 利用Java动态生成 PDF 文档

    利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...

  3. html 生成pdf

    HTML生成PDF(c#) 最近因为工作需要,小小的研究了一下HTML生成PDF的方法,这方面的内容很多,但要么是不尽如人意的方法,要么就是那种收费的类库!为了广大.neter的福利,把自己的一点小小 ...

  4. iTextSharp生成pdf的一个简单例子

    效果图: 参考:http://www.cnblogs.com/CareySon/archive/2011/11/09/2243496.html http://www.cnblogs.com/julyl ...

  5. 生成 PDF 全攻略【2】在已有PDF上添加内容

    项目在变,需求在变,不变的永远是敲击键盘的程序员..... PDF 生成后,有时候需要在PDF上面添加一些其他的内容,比如文字,图片.... 经历几次失败的尝试,终于获取到了正确的代码书写方式. 在此 ...

  6. PHP 生成PDF

    一个项目中需要用到网页生成PDF,就是将整个网页生成一个PDF文件, 以前也用过HTML2PDF,只能生成一些简单的HTML代码,复杂的HTML + css 生成的效果惨不忍睹, 百度了一下,发现有个 ...

  7. 用js生成PDF的方案

    在java里,我们常用Itext来生成pdf,在pdf文件里组合图片,文字,画表格,画线等操作,还会遇到中文支持的问题. 那好,现在想直接在web前端就生成pdf怎么办,目前有以下几个解决方案 1:J ...

  8. 使用TCPDF插件生成pdf以及pdf的中文处理

    目录(?)[+] 多种多样的pdf开发库 WKHTMLTOPDF 2FPDF 3TCPDF 中文问题   做了这么多年项目,以前只是在别人的项目中了解过PHP生成pdf文件,知道并不难,但是涉及到了p ...

  9. linux下编译bib、tex生成pdf文件

    实验: 在linux环境下,编译(英文)*.bib和*.tex文件,生成pdf文件. 环境: fedora 20(uname -a : Linux localhost.localdomain 3.19 ...

随机推荐

  1. Centos7自动式脚本搭建jumpserver

    JumpServer脚本 这里需要安装阿里的yum源和epel源并解压: epel源地址https://mirrors.tuna.tsinghua.edu.cn/epel// 安装阿里互联网yum仓库 ...

  2. POJ-1655 Balancing Act(树的重心)

    Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the t ...

  3. Android RecyclerViewSwipeDismiss:水平、垂直方向的拖曳删除item

     Android RecyclerViewSwipeDismiss:水平.垂直方向的拖曳删除item RecyclerViewSwipeDismiss是一种支持RecyclerView的水平.垂直 ...

  4. Python 4 循环语句while

    while  [条件]:        条件这里满足布尔运算True则无限循环while里面代码. 固定条件的 基本的while循环, 如果if匹配那么 则执行打印登录成功,和break跳出整个循环, ...

  5. printf()参数的处理

    下面程序的输出为? #include <stdio.h> int main(void) { ,b=,c=; printf(),(c = c*)); ; } 答案是110..40..60 这 ...

  6. O - String Problem KMP 字符串最小表示法

    Give you a string with length N, you can generate N strings by left shifts. For example let consider ...

  7. RSA 数据加密和数字签名算法

    PKCS8EncodedKeySpec pkcs8KeySpec = KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Pr ...

  8. UVA 10859 树形DP

    很明显的树形DP了,设状态dp[i][0],dp[i][1].枚举子节点放或不放的两种状态. 在此学到一种不同于一般处理的方法,题目要求被两灯照亮的边尽量多,反过来即被一灯照亮的尽量少设为e.又需要的 ...

  9. java如何实现替换指定位置的指定字符串的功能

    /**  * @创建日期 2013-07-15  * @创建时间 14:25:59  * @版本号 V 1.0  */ public class CosTest {     public static ...

  10. java调用百度地图API依据地理位置中文获取经纬度

    百度地图api提供了非常多地图相关的免费接口,有利于地理位置相关的开发,百度地图api首页:http://developer.baidu.com/map/. 博主使用过依据地理依据地理位置中文获取经纬 ...