之前實現了html直接轉換為word文檔的功能,那么是否也同樣可以直接轉換為pdf文檔呢,網上搜了下html to pdf 的開源插件有很多 如:wkhtmltopdf,pdfsharp,itextsharp等
本文使用itextsharp實現如何將html文件轉換為pdf文檔
首先使用Nuget安裝itextsharp插件
-
Install-Package itextsharp.xmlworker
創建FileContentResult文件繼承自ActionResult,方法HtmlToPdf中實現了如何將一段html轉換為pdf文檔邏輯,itextsharp.xmlworker能夠支持豐富的css和html標簽,但是有一個很大的缺點就是不支持中文,網上的一些解決中文字體的邏輯,在新版里面已經不支持了,在以下的示例代碼中已經解決此問題,重點是以下兩部代碼:
FontFactory.RegisterDirectories();//注冊當前系統中所支持的字體
worker.ParseXHtml(pdfWriter, document, new MemoryStream(Encoding.UTF8.GetBytes(sbHtml.ToString())), null, Encoding.UTF8, new UnicodeFontFactory()); //指定要使用的字體
-
public class PdfContentResult : ActionResult
-
{
-
public PdfContentResult() : this(null, null) { }
-
-
public PdfContentResult(string viewName) : this(null, viewName) { }
-
-
public PdfContentResult(object model) : this(model, null) { }
-
-
public PdfContentResult(object model, string viewName)
-
{
-
this.ViewName = viewName;
-
ViewData = null != model ? new ViewDataDictionary(model) : null;
-
}
-
-
public ViewDataDictionary ViewData { get; set; } = new ViewDataDictionary();
-
-
public string ViewName { get; set; }
-
-
public IView View { get; set; }
-
-
public override void ExecuteResult(ControllerContext context)
-
{
-
if (String.IsNullOrEmpty(ViewName))
-
{
-
ViewName = context.RouteData.GetRequiredString("action");
-
}
-
if (ViewData == null)
-
{
-
ViewData = context.Controller.ViewData;
-
}
-
ViewEngineResult result = ViewEngines.Engines.FindView(context, ViewName, null);
-
View = result.View;
-
-
StringBuilder sbHtml = new StringBuilder();
-
TextWriter txtWriter = new StringWriter(sbHtml);
-
ViewContext viewContext = new ViewContext(context, View, ViewData, context.Controller.TempData, txtWriter);
-
result.View.Render(viewContext, txtWriter);
-
-
HttpResponseBase httpResponse = context.HttpContext.Response;
-
httpResponse.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
-
-
//加入此頭部文件會直接下載pdf文件,而不是在瀏覽器中預覽呈現
-
//context.HttpContext.Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}.pdf", ViewName));
-
-
HtmlToPdf(sbHtml, httpResponse);
-
-
result.ViewEngine.ReleaseView(context, View);
-
}
-
-
private static void HtmlToPdf(StringBuilder sbHtml, HttpResponseBase httpResponse)
-
{
-
using (Document document = new Document(PageSize.A4, 4, 4, 4, 4))
-
{
-
using (PdfWriter pdfWriter = PdfWriter.GetInstance(document, httpResponse.OutputStream))
-
{
-
document.Open();
-
FontFactory.RegisterDirectories();//注冊系統中所支持的字體
-
XMLWorkerHelper worker = XMLWorkerHelper.GetInstance();
-
//UnicodeFontFactory 自定義實現解決itextsharp.xmlworker 不支持中文的問題
-
worker.ParseXHtml(pdfWriter, document, new MemoryStream(Encoding.UTF8.GetBytes(sbHtml.ToString())), null, Encoding.UTF8, new UnicodeFontFactory());
-
document.Close();
-
}
-
}
-
}
-
}
UnicodeFontFactory完整代碼
-
public class UnicodeFontFactory : FontFactoryImp
-
{
-
static UnicodeFontFactory()
-
{
-
-
}
-
public override Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color, bool cached)
-
{
-
return FontFactory.GetFont("arial unicode ms", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
-
}
-
}
如何確定哪些字體在itextsharp中是支持中文的呢,可以通過下面這個小程序驗證輸出所有的字體名稱,及是否支持中文
通過控制台應用程序執行完成后,打開生成的pdf文件,查看 字體名稱是否有中文 " 我支持中文" ,如果存在則表示支持中文,否則不支持中文
-
Document document = new Document();
-
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(@"c:\pdf\pdf.pdf", FileMode.Create));
-
document.Open();
-
-
FontFactory.RegisterDirectories();
-
-
foreach (var item in FontFactory.RegisteredFonts)
-
{
-
Font font = FontFactory.GetFont(item, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
-
document.Add(new Paragraph(item + "<p>我支持中文</p>", font));
-
}
-
document.Close();
上面說了如何轉換html為pdf及怎么解決中文字體的問題,那么怎么使用定義的PdfContentResult呢,
使用方式一:直接在控制器的Action方法中返回PdfContentResult實例
-
public class PdfController : Controller
-
{
-
// GET: Pdf
-
public ActionResult Index()
-
{
-
return new PdfContentResult(null,"index");
-
}
-
}
使用方式二:添加Controller類的拓展方法,然后在控制器的Action方法中返回對應的拓展方法
-
public static class ControllerExtensions
-
{
-
public static PdfContentResult Pdf(this Controller controller, object model)
-
{
-
return new PdfContentResult(model);
-
}
-
-
public static PdfContentResult Pdf(this Controller controller, object model, string fileName)
-
{
-
return new PdfContentResult(model, fileName);
-
}
-
-
public static PdfContentResult Pdf(this Controller controller, string fileName)
-
{
-
return new PdfContentResult(fileName);
-
}
-
}
這種感覺用起來是不是與return view();一樣
-
public class PdfController : Controller
-
{
-
// GET: Pdf
-
public ActionResult Index()
-
{
-
return this.Pdf(null, "index");
-
}
-
}
可能有人會問pdf文檔的內容在哪里維護,直接打開Action對應的View視圖,像寫mvc頁面一樣布局pdf內容就可以了
至於itextsharp更多功能支持,請參考此文檔:http://developers.itextpdf.com/