使用iText7的pdfHtml库,将html转成pdf,官方:https://itextpdf.com/en/demos/convert-html-css-to-pdf-free-online;
官方示例:
using System.IO; using iText.Html2pdf; namespace WebsiteDemoPdfHtml { class Program { private static string ORIG = "/uploads/input.html"; private static string OUTPUT_FOLDER = "/myfiles/"; static void Main(string[] args) { string pdfDest = OUTPUT_FOLDER + "output.pdf"; HtmlConverter.ConvertToPdf(new FileStream(ORIG, FileMode.Open), new FileStream(pdfDest, FileMode.Create)); } } }
官方可以下载到详细的使用文档;支持CSS3;支持css @page规则控制打印设置选项;
以html作为打印模板,往往需要打印多项数据,我的实现是这样的(与官方模板不同):使用双大括号{{field}}作为书签,使用正则替换插入数据;如果有列表数据,则以注释<!--items-start-->作为子模板开始,以<!--items-end-->作为子模版结束;
hello.html文件:
<!DOCTYPE html> <html lang="zh-cn" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title>Colossal</title> <meta name="description" content="Gloria is an out-of-work party girl ..." /> <style> @page { @bottom-right { content: "Page "counter(page)" of "counter(pages); } } .poster { width: 120px; float: right; } .director { font-style: italic; } body { font-family: serif; } .imdb { font-size: 0.8em; } a { color: red; } </style> </head> <body> <img src="{{ImageUrl}}" class="poster" /> <h1>{{Title}}</h1> <div class="director">{{Director}}</div> <div class="description">{{Description}}</div> <div class="imdb">{{Imdb}}<a href="{{Href}}">{{HrefContent}}</a></div> <ul> <!--names-start--> <li>{{Name}}</li> <!--names-end--> </ul> </body> </html>
示例代码:
var pdfDest = "myfiles/" + "hello.pdf"; var pdfWriter = new PdfWriter (pdfDest); var pdf = new PdfDocument (pdfWriter); var pageSize = PageSize.A4; // 设置默认页面大小,css @page规则可覆盖这个 pdf.SetDefaultPageSize (pageSize); var mediaDeviceDescription = new MediaDeviceDescription (MediaType.PRINT); // 指当前设备类型,如果是预览使用SCREEN mediaDeviceDescription.SetWidth (pageSize.GetWidth ()); var properties = new ConverterProperties (); properties.SetBaseUri ("htmls"); // 设置根目录 properties.SetCharset ("utf-8"); var provider = new DefaultFontProvider (true, true, true); // 第三个参数为True,以支持系统字体,否则不支持中文 properties.SetFontProvider (provider); properties.SetMediaDeviceDescription (mediaDeviceDescription); var dic = new Dictionary<String, String> { ["{{ImageUrl}}"] = "./test_files/5687441010153797724.jpg", ["{{Title}}"] = "Colossal (2016) 中文字体", ["{{Director}}"] = "Directed by Nacho Vigalondo", ["{{Description}}"] = "Gloria is an out-of-work party girl forced to leave her life in New York City,and move back home. When reports surface that a giant creature isdestroying Seoul, she gradually comes to the realization that she issomehow connected to this phenomenon.", ["{{Imdb}}"] = "Read more about this movie on", ["{{Href}}"] = "www.imdb.com/title/tt4680182", ["{{HrefContent}}"] = "IMDB" }; var htmlTemplate = File.ReadAllText ("htmls/hello.html"); var match = Regex.Match (htmlTemplate, @"<!--names-start-->(.|\s)+?<!--names-end-->"); // 匹配子模版 if (match == null) return; var template = match.Value.Substring ("<!--names-start-->".Length, match.Value.Length - "<!--names-start--><!--names-end-->".Length); var names = new List<String> { "张三", "李四", "王五" }; var sb = new StringBuilder ("<!--names-start-->"); foreach (var name in names) { sb.Append (template.Replace ("{{Name}}", name)); // 子模版赋值 } sb.Append ("<!--names-end-->"); htmlTemplate = htmlTemplate.Replace (match.Value, sb.ToString ()); // 完成子模版部分 var regex = new Regex (String.Join ("|", dic.Keys)); var html = regex.Replace (htmlTemplate, m => dic[m.Value]); // 模板字段赋值 HtmlConverter.ConvertToPdf (html, pdf, properties);
实现效果: