原文:[ASP.net MVC] 将HTML转成PDF档案,使用iTextSharp套件的XMLWorkerHelper (附上解决显示中文问题)
[ASP.net MVC] 将HTML转成PDF档案,使用iTextSharp套件的XMLWorkerHelper (附上解决显示中文问题)
前言
最近专案又遇到需要制作PDF文件的需求,这次还要额外控制PDF档案的其他功能,我的直觉马上联想到使用iTextSharp来实现
一般使用iTextSharp套件要塞资料到PDF档案里的话,大概要先把Phrase、PdfPTable、PdfPCell……等等几个物件叫出来,然後加入至Document物件
※请参考其他网友文章:使用ASP .NET (C#) 产生PDF档的好帮手—iTextSharp library (上)、使用ASP .NET (C#) 产生PDF档的好帮手—iTextSharp library (下)
但由於专案要求有 [网页预览+下载PDF(把预览的网页画面转出到PDF档)功能]
因为已经先有Html网页画面了,我比较懒,所以在网路上寻求有没有把Html网页转PDF档的iTextSharp实现办法
虽然过程中有考量用:[ASP.net MVC] 在Web专案上使用Pechkin套件将网页转成PDF档
但Pechkin没办法进一步控制PDF档案的详细功能,它只能仅仅印出来而已
所以整个需求大致是:利用iTextSharp套件将网页档(或HTML文字)转成PDF档
?
而iTextSharp一般在网路上比较常见,都是使用内建的HtmlWorker物件来实现
※HtmlWorker已有中文字显示问题的解决办法,请参考其他网友文章:使用iTextSharp 5将html档转成PDF档
但本文使用的是XMLWorkerHelper物件来Parse网页Html文字
因为比起HtmlWorker物件,XMLWorkerHelper类别支援更多CSS和Html标签(例如
),但缺点预设不支援中文字
不过中文字显示问题,已经在下文的Sample Code中解决了
?
实作
先为Web专案透过NuGet加入以下参考
以下是要输出成PDF档案的范例静态网页内容,还没套程式,因为套程式塞资料到画面不是本文的重点
此网页Html该注意的重点都在说明注解里
[厂商名称] |
|||||
Taiwan Limited 4F,144 Changchun Rd., Taipei 104, Taiwan |
[页码]/[总页数] | ||||
XXX借用函证书 |
|||||
日期:民国[函证民国日期] | |||||
敬启者:[经销商全衔] | |||||
XXX 借用人:[员工姓名] | |||||
[厂商名称]将於 [存货盘点民国日期] 进行例行性存货盘点,恳请协助清点敝公司借予 贵公司之存货品名及数量是否与下列明细相符,并盖章回传以兹证明。 | |||||
敬祝 商祺 | |||||
此致 [厂商名称] | |||||
以下为截至 民国[函证民国日期] 为止,贵公司借用之存货明细: | |||||
|
|||||
确认无误,特此证明。 | |||||
|
|||||
民国[函证民国日期] | |||||
经销商代号: 出借者工号: |
该Html静态网页的执行内容
※补充说明,以上最外层的table容器宽度如果是固定宽度而非100%宽,Document物件又设为PageSize.A4的话,输出成PDF很可能会变这样↓
↑这种情况虽然调参数Document doc=new Document(PageSize.A3);即可解决,但比较通用的办法还是把最外层的容器宽度设为100%以符合PDF各种A4 、A3大小的宽度
?
接下来在专案中加入一个自订类别UnicodeFontFactory.cs,待会输出PDF时要使用此类别来解决XMLWorkerHelper不支援中文字问题
UnicodeFontFactory.cs代码完整内容
using iTextSharp.text; using iTextSharp.text.pdf; using iTextSharp.tool.xml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Web; public class UnicodeFontFactory : FontFactoryImp { private static readonly string arialFontPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "arialuni.ttf");//arial unicode MS是完整的unicode字型。 private static readonly string 标楷体Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "KAIU.TTF");//标楷体 public override Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color, bool cached) { //可用Arial或标楷体,自己选一个 BaseFont baseFont = BaseFont.CreateFont(标楷体Path, BaseFont.IDENTITY_H, BaseFont.EMBEDDED); return new Font(baseFont, size, style, color); } }
而在HomeController里,Html转PDF的完整范例代码
using iTextSharp.text; using iTextSharp.text.pdf; using iTextSharp.tool.xml; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Web; using System.Web.Mvc; namespace MvcApplicationPDF.Controllers { public class HomeController : Controller { ////// 执行此Url,下载PDF档案 /// ///public ActionResult DownloadPdf() { WebClient wc = new WebClient(); //从网址下载Html字串 string htmlText = wc.DownloadString("http://localhost:3056/Preview.html"); byte[] pdfFile = this.ConvertHtmlTextToPDF(htmlText); return File(pdfFile, "application/pdf", "范例PDF档.pdf"); } /// /// 将Html文字 输出到PDF档里 /// /// ///public byte[] ConvertHtmlTextToPDF(string htmlText) { if (string.IsNullOrEmpty(htmlText)) { return null; } //避免当htmlText无任何html tag标签的纯文字时,转PDF时会挂掉,所以一律加上 标签 htmlText = "
" + htmlText + "
"; 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); //指定文件预设开档时的缩放为100% PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, 0, doc.PageSize.Height, 1f); //开启Document文件 doc.Open(); //使用XMLWorkerHelper把Html parse到PDF档里 XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msInput, null, Encoding.UTF8, new UnicodeFontFactory()); //将pdfDest设定的资料写到PDF档 PdfAction action = PdfAction.GotoLocalPage(1, pdfDest, writer); writer.SetOpenAction(action); doc.Close(); msInput.Close(); outputStream.Close(); //回传PDF档案 return outputStream.ToArray(); } } }
执行结果:
结语
将Html转成PDF,使用Pechkin或iTextSharp各有优缺点
画面呈现当然是Pechkin比较忠於原始网页(因为采用Webkit引擎),如果没要进一步控制PDF档案功能的话,可使用Pechkin
如果要进一步控制PDF功能而且画面只是单纯的白纸黑字,就可以改用iTextSharp套件
参考文章
Display Unicode characters in converting Html to Pdf
How to set a default zoom percent to “100%” using iTextSharp 4.0.2?