C# html生成PDF遇到的问题,从iTextSharp到wkhtmltopdf
我们的网站业务会生成一个报告,用网页展示出来,要有生成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的更多相关文章
- C#生成PDF总结
(一)C#生成PDF总结 (1)iTextSharp控件对iTextSharp研究还可以表格.文字.各种GDI对象,图片,水印,文字旋转(2)aspose的控件(3)PDF Library这个类库(只 ...
- 利用Java动态生成 PDF 文档
利用Java动态生成 PDF 文档,则需要开源的API.首先我们先想象需求,在企业应用中,客户会提出一些复杂的需求,比如会针对具体的业务,构建比较典型的具备文档性质的内容,一般会导出PDF进行存档.那 ...
- html 生成pdf
HTML生成PDF(c#) 最近因为工作需要,小小的研究了一下HTML生成PDF的方法,这方面的内容很多,但要么是不尽如人意的方法,要么就是那种收费的类库!为了广大.neter的福利,把自己的一点小小 ...
- iTextSharp生成pdf的一个简单例子
效果图: 参考:http://www.cnblogs.com/CareySon/archive/2011/11/09/2243496.html http://www.cnblogs.com/julyl ...
- 生成 PDF 全攻略【2】在已有PDF上添加内容
项目在变,需求在变,不变的永远是敲击键盘的程序员..... PDF 生成后,有时候需要在PDF上面添加一些其他的内容,比如文字,图片.... 经历几次失败的尝试,终于获取到了正确的代码书写方式. 在此 ...
- PHP 生成PDF
一个项目中需要用到网页生成PDF,就是将整个网页生成一个PDF文件, 以前也用过HTML2PDF,只能生成一些简单的HTML代码,复杂的HTML + css 生成的效果惨不忍睹, 百度了一下,发现有个 ...
- 用js生成PDF的方案
在java里,我们常用Itext来生成pdf,在pdf文件里组合图片,文字,画表格,画线等操作,还会遇到中文支持的问题. 那好,现在想直接在web前端就生成pdf怎么办,目前有以下几个解决方案 1:J ...
- 使用TCPDF插件生成pdf以及pdf的中文处理
目录(?)[+] 多种多样的pdf开发库 WKHTMLTOPDF 2FPDF 3TCPDF 中文问题 做了这么多年项目,以前只是在别人的项目中了解过PHP生成pdf文件,知道并不难,但是涉及到了p ...
- linux下编译bib、tex生成pdf文件
实验: 在linux环境下,编译(英文)*.bib和*.tex文件,生成pdf文件. 环境: fedora 20(uname -a : Linux localhost.localdomain 3.19 ...
随机推荐
- Ansible实现zabbix服务器agent端批量部署
项目需求:由于搭建zabbix,需要每台服务器都需要安装监控端(agent)正常的的操作是一台一台去安装,这样确实有点浪费时间,这里为大家准备了一款开源 的自动化运维工具Ansible,相信大家也很熟 ...
- HDU 3152 Obstacle Course(优先队列,广搜)
题目 用优先队列优化普通的广搜就可以过了. #include<stdio.h> #include<string.h> #include<algorithm> usi ...
- python运算符及优先级
计算机可以进行的运算有很多种,可不只加减乘除这么简单,运算按种类可分为算数运算.比较运算.逻辑运算.赋值运算.成员运算.身份运算.位运算. 一.算数运算 以下假设变量:a=10,b=20 二.比较运算 ...
- BZOJ 1724 USACO 2006 Nov. 切割木板
倒过来的合并果子? 做法与合并果子一样 维护一个小根堆,每次取出最小的两个数进行合并 #include<cstdio> #include<algorithm> #include ...
- 个人学习记录--取表中Name相同的最大值,非Group By,可延伸
), qy ), je INT); INSERT INTO @t SELECT '产品一', '北京', UNION ALL SELECT '产品一', '上海', UNION ALL SELECT ...
- hdu2013 蟠桃记【C++】
蟠桃记 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- Java基础学习总结(41)——JPA常用注解
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA由EJB 3.0软件专 ...
- UVa - 11452 - Dancing the Cheeky-Cheeky
先上题目: F. Dancing the Cheeky-Cheeky Context The Cheeky-Cheeky is a new song. They dance it in Mula, ...
- Sencha Toucha 2.1 文件上传
javascript代码: Ext.onReady(function() { Ext.create('Ext.form.Panel', { title: 'Upload a Photo', width ...
- nyoj_85_有趣的数_201312122130
有趣的数 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 把分数按下面的办法排成一个数表. 1/1 1/2 1/3 1/4..... 2/1 2/2 ...