原文:[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标签(例如<hr/>),但缺点预设不支援中文字

不过中文字显示问题,已经在下文的Sample Code中解决了

?

实作

先为Web专案透过NuGet加入以下参考

以下是要输出成PDF档案的范例静态网页内容,还没套程式,因为套程式塞资料到画面不是本文的重点

此网页Html该注意的重点都在说明注解里

      <!--设定width为100%以刚好符合PDF文件的宽度-->
<!--如果width为固定宽度的话,C#那边可能要改写成Document doc = new Document(PageSize.A3)-->
<!--此table已调整好高度刚好符合PDF A4一页的高度了-->
<table style='width:100%;' >
<tr >
<td colspan='2' style='color:#808080;'>
<h2>[厂商名称]</h2>
</td>
</tr>
<tr style='font-size:13px;'>
<td style='width:600px;color:#808080;font-size:16px;'>Taiwan Limited<br />4F,144 Changchun Rd., Taipei 104, Taiwan</td>
<td style='width:80%;color:#808080;font-size:16px;text-align:right;'>[页码]/[总页数]</td>
</tr> <tr>
<td colspan='2' style='text-align:center; height:90px;'><h1>XXX借用函证书</h1></td>
</tr>
<tr>
<td colspan='2' style='text-align:right;font-size:20px;'> 日期:民国[函证民国日期] </td>
</tr>
<tr>
<td colspan='2' style='height:10px;font-size:20px;' > 敬启者:[经销商全衔] </td>
</tr>
<tr>
<td colspan='2' style='height:30px;font-size:20px;' > XXX 借用人:[员工姓名] </td>
</tr>
<tr>
<td colspan='2' style='height:50px;line-height:27px;font-size:20px;vertical-align:bottom;' > [厂商名称]将於&nbsp;[存货盘点民国日期]&nbsp;进行例行性存货盘点,恳请协助清点敝公司借予&nbsp;&nbsp;贵公司之存货品名及数量是否与下列明细相符,并盖章回传以兹证明。 </td>
</tr>
<tr>
<td colspan='2' style='height:40px;font-size:20px;' > 敬祝&nbsp;&nbsp;商祺 </td>
</tr>
<tr>
<td colspan='2' style='height:30px;line-height:20px;font-size:20px;' > 此致&nbsp;&nbsp;[厂商名称] </td>
</tr>
<tr>
<td colspan='2' style='font-size:20px;line-height:20px;' > 以下为截至 民国[函证民国日期] 为止,贵公司借用之存货明细: </td>
</tr>
<tr>
<td colspan='2' style='height:280px;vertical-align:top;font-size:20px;' >
<table style='border:1px solid #000000; width:100%;' cellpadding='0' cellspacing='0'>
<tr>
<td style='border:1px solid #000000;text-align:center;font-size:20px;'>No</td>
<td style='border:1px solid #000000;text-align:center;font-size:20px;'>品号</td>
<td style='border:1px solid #000000;text-align:center;font-size:20px;'>品名</td>
<td style='border:1px solid #000000;text-align:center;font-size:20px;'>数量</td>
</tr>
</table> </td>
</tr>
<tr>
<td colspan='2' style='font-size:20px;' > 确认无误,特此证明。 </td>
</tr>
<tr>
<td colspan='2' style='height:200px; ' >
<div style='float:right;'>
<table style='border:1px solid #000000; ' cellpadding='0' cellspacing='0'>
<tr>
<td style='border:1px solid #000000;width:180px;height:180px;text-align:right; vertical-align:bottom;padding-bottom:10px;font-size:16px;'>经销商公司章</td>
<td style='border:1px solid #000000;width:180px;height:180px;text-align:right;vertical-align:bottom;padding-bottom:10px;font-size:16px;'>借用人签章</td>
</tr>
</table>
</div>
</td>
</tr>
<tr>
<td colspan='2' style='text-align:right;font-size:20px;' > 民国[函证民国日期] </td>
</tr>
<tr style='font-size:13px;height:50px;'>
<td colspan='2' style='color:#808080;font-size:16px; vertical-align:bottom;' > 经销商代号: 出借者工号: </td>
</tr>
</table>

该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
{ /// <summary>
/// 执行此Url,下载PDF档案
/// </summary>
/// <returns></returns>
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");
}
/// <summary>
/// 将Html文字 输出到PDF档里
/// </summary>
/// <param name="htmlText"></param>
/// <returns></returns>
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);
//指定文件预设开档时的缩放为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?

[ASP.net MVC] 将HTML转成PDF档案,使用iTextSharp套件的XMLWorkerHelper (附上解决显示中文问题)的更多相关文章

  1. ASP.NET MVC 3 loginUrl自动变成Account/Login,并且发生404错误的解决方法

    http://www.cnblogs.com/think8848/archive/2011/07/08/2100814.html ASP.NET MVC 3 loginUrl自动变成Account/L ...

  2. 基于ITextSharp插件在ASP.NET MVC中将图表导出为PDF

    样本: 在这个示例中,我们使用的是微软给我们提供的数据库,也就是家喻户晓的Northwind数据库.要下载Microsoft的免费样本Northwind数据库,您需要访问以下URL.下载Northwi ...

  3. asp.net mvc(一) ----------简单封装成通用的List<T>集合

    asp.net mvc(一) 这些天开始学习asp.net mvc,用传统的asp.net已经快四的年了,刚开始接触asp.net mvc确认感觉有点不适应,主要体现在asp.net mvc的实现上. ...

  4. 【精品分享二】ASP.NET MVC系列精品图书高清PDF下载

    更多图书请关注:第一教育云电子书平台  http://book.1eduyun.com/ 注:本专题提供的所有的电子书下载资源均系收集于百度云,本网站(http://book.1eduyun.com/ ...

  5. ASP.NET MVC 项目直接预览PDF文件

    背景及需求 项目使用的是MVC4框架,其中有一个功能是根据设置生成PDF文件,并在点击时直接预览. 实现过程 1.第一版实现代码: HTML内容 @{ Layout = null; } <!DO ...

  6. 【ASP.NET MVC】"[A]System.Web.WebPages.Razor.Configuration.HostSection 无法强制转换为 ..."的解决办法

    1.错误页面: “/”应用程序中的服务器错误. [A]System.Web.WebPages.Razor.Configuration.HostSection 无法强制转换为 [B]System.Web ...

  7. ASP.NET MVC 5 - 验证编辑方法(Edit method)和编辑视图(Edit view)

    在本节中,您将验证电影控制器生成的编辑方法(Edit action methods)和视图.但是首先将修改点代码,使得发布日期属性(ReleaseDate)看上去更好.打开Models \ Movie ...

  8. ASP.NET MVC 5– 使用Wijmo MVC 5模板1分钟创建应用

    开始使用 使用ComponentOne Studio for ASP.NET Wijmo制作MVC5应用程序,首先要做的是安装Studio for ASP.NET Wijmo . 测试环境 VS201 ...

  9. ASP.NET MVC 5 - 查询Details和Delete方法

    在这部分教程中,接下来我们将讨论自动生成的Details和Delete方法. 查询Details和Delete方法 打开Movie控制器并查看Details方法. public ActionResul ...

随机推荐

  1. Linux下Bash入门学习笔记

    学习好shell编程是很有用的,可以使用shell脚本轻巧地完成有趣的工作. 本文地址:http://www.cnblogs.com/yhLinux/p/4047516.html 1. Bash实例, ...

  2. 小记初试tornado与ajax,一些注意点

    一. 在 tornado模板中使用自定义方法 在tornado中可以使用两种方式,达到在模板中调用自定义方法的效果,第一种是使用UIMethod 和UIModule. 1.UIMethod使用方法示例 ...

  3. 关于selenium截图

    没时间深入研究源代码,凭调试解决了非浏览器级别的滚动条截图. 首先,定位到带有滚动条的元素,通过xpath. 其次,获取scrollheight和clientheight. 第三,循环截图,循环截图的 ...

  4. delphi7 编译程序时报win32.indcu.a病毒的解决方法

    Delphi7用了很久一直都没问题,同一个工程文件昨天编译时mod32还不会报毒,今天重新编译时,生成的exe突然nod32报毒. 提示: “Project1.exe Win32/Induc.A 病毒 ...

  5. 一些有用的Javascript Function :-)

    1.验证完整的日期格式:(yyyy-MM-dd)function checkDate(RQ) { var date = RQ; var result = date.match(/^(\d{1,4})( ...

  6. 【整理】--【字符设备】分配设备号register_chrdev_region()、alloc_chrdev_region() 和 register_chrdev()

    (1) 分配设备编号,注册设备与注销设备的函数均在fs.h中声明,如下: extern int register_chrdev_region(dev_t,unsigned int,const char ...

  7. linux下显示dd命令的进度:

    linux下显示dd命令的进度: dd if=/dev/zero of=/tmp/zero.img bs=10M count=100000 想要查看上面的dd命令的执行进度,可以使用下面几种方法: 比 ...

  8. Yii2中的入口文件环境配置

    默认的Debug配置 在入口文件中 defined ( 'YII_DEBUG' ) or define ( 'YII_DEBUG', true ); defined ( 'YII_ENV' ) or ...

  9. 将asp.net webapi的运行时版本由4.0升级到4.5.1时遇到的问题及解决

    更新package 更改.net运行时的版本之后,出现了错误提示,说需要改新以下组件: EntityFramework, EntityFramework.zh-Hans, Microsoft.AspN ...

  10. 计划参照mysql-proxy编写mssql-proxy

    目前使用haproxy做了mssql多个读库的负载均衡,在生产环境中运行得不错. 不过,这个方案有缺点:客户端需要选择是使用读库,还是写库.这样还是不够方便,如果能够实现自动路由就更好了,即让hapr ...