前言:

最近在做老师交代的一个在线写实验报告的小项目中,有这么个需求:把学生提交的实验报告(HTML形式)直接转成PDF,方便下载和打印。

以前都是直接用rdlc报表实现的,可这次牵扯到图片,并且更为重要的一点是 PDF的格式得跟学生提交的HMTL页面一样。经过网上查阅资料,

找到了ITextSharp插件。

ITextSharp很强大,但是在处理HMTL中的 img标签时,src中只能是绝对路径。

解决方法我写在了另一篇文章中

正文:

ITextSharp就不多介绍了。项目的链接下载链接为http://files.cnblogs.com/files/zuochengsi-9/H%E8%BD%ACPDF.zip

下开始项目之前得添加 ITextSharp.dll和ITextSharp.xmlworker.dll  后者是解决中文用的

可以从NuGet中下载引用,具体方法就不介绍了。网上很多解决方案。

项目结构图:

下面先说下主要操作:

步骤:1、将本地的某个视图转成字符串。

2、将字符串整合成PDF的文档,并返回byte数组。

3、讲比特流写到HTTP内容主体的二进制流中去。

视图转字符串代码:

首先新建两个类,转字符串的逻辑主要在RenderViewToString方法中。

 public class HtmlViewRenderer{public string RenderViewToString(Controller controller, string viewName, object viewData){var renderedView = new StringBuilder();using (var responseWriter = new StringWriter(renderedView)){var fakeResponse = new HttpResponse(responseWriter);var fakeContext = new HttpContext(HttpContext.Current.Request, fakeResponse);var fakeControllerContext = new ControllerContext(new HttpContextWrapper(fakeContext), controller.ControllerContext.RouteData, controller.ControllerContext.Controller);var oldContext = HttpContext.Current;HttpContext.Current = fakeContext;using (var viewPage = new ViewPage()){var html = new HtmlHelper(CreateViewContext(responseWriter, fakeControllerContext), viewPage);html.RenderPartial(viewName,viewData);HttpContext.Current = oldContext;}}return renderedView.ToString();}private static ViewContext CreateViewContext(TextWriter responseWriter, ControllerContext fakeControllerContext){return new ViewContext(fakeControllerContext, new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), responseWriter);}}

   public class FakeView : IView{public void Render(ViewContext viewContext, TextWriter writer){throw new NotImplementedException();}}

再新建一个控制器,调用刚刚写好的RenderViewToString方法。(后面会再新建一个HomeController,继承这个PdfViewController,再在HomeController的Action里调用ViewPdf就行)

   public class PdfViewController : Controller{private readonly HtmlViewRenderer htmlViewRenderer;public PdfViewController(){this.htmlViewRenderer = new HtmlViewRenderer();}protected string ViewPdf(string viewName,object model){// Render the view html to a string.string htmlText = this.htmlViewRenderer.RenderViewToString(this, viewName,model);return htmlText;}}

"字符串转byte[]"   (这个方法放在后面写的HomeController中)

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的文件,建構子沒填的話預設直式A4PdfWriter 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();}

其中XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msInput, null, Encoding.UTF8, new UnicodeFontFactory());这段代码中的“UnicodeFontFactory”类,封装了中文字体的设置。代码如下:

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);} }

再新建一个类,用来将比特流输出到response.OutputStream中:

 public class BinaryContentResult : ActionResult{private readonly string contentType;private readonly byte[] contentBytes;public BinaryContentResult(byte[] contentBytes, string contentType){this.contentBytes = contentBytes;this.contentType = contentType;  }public override void ExecuteResult(ControllerContext context){var response = context.HttpContext.Response;response.Clear();response.Cache.SetCacheability(HttpCacheability.Public);response.ContentType = this.contentType;           //下面这段加上就是一个下载页面            response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode("文件名.pdf", System.Text.Encoding.UTF8));            using (var stream = new MemoryStream(this.contentBytes)){stream.WriteTo(response.OutputStream);stream.Flush();}}}

现在来看一下HomeController

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;
using HTML转PDF.Models;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.tool.xml;
using ReportManagement;namespace HTML转PDF.Controllers
{public class HomeController :PdfViewController{//// GET: /Home/public ActionResult Index(){return View();}/// <summary>/// 執行此Url,下載PDF檔案/// </summary>/// <returns></returns>public ActionResult DownloadPdf(){var person = new People("左成");string htmlText = this.ViewPdf("Preview",person);byte[] pdfFile = this.ConvertHtmlTextToPDF(htmlText);return new BinaryContentResult(pdfFile, "application/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的文件,建構子沒填的話預設直式A4PdfWriter 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();}}
}

步骤二的ConvertHtmlTextToPDF方法,我就直接放在了这里面,没管那些设计原则了。上面代码中“Preview”是本地的一个视图,最好和HomeController在一个区域里面,不然得改步骤一的代码。

最后是我的前台部分的代码,写的很简单(Preview.cshtml)。

1
2
3
4
@model HTML转PDF.Models.People
  <!-- 下面是我机器上的绝对路径  -->        
<img src="E:\12.bmp" width="64" height="64" />
<p>大家好,我叫"@Model.Name"</p>

  

特别注意:关于跳转到我们写的“DownloadPdf”Action时,千万不要用ajax.ActionLink(坑了我好久)。不然会出现乱码,我也没找到解决方案。

参考资料:http://www.tuicool.com/articles/aUfqeu

http://dwtedx.com/itshare_233.html

转载请注明出处:http://www.cnblogs.com/zuochengsi-9/p/5483808.html

转载于:https://www.cnblogs.com/waw/p/7235894.html

ASP.Net MVC——使用 ITextSharp 完美解决HTML转PDF(中文也可以)相关推荐

  1. IntelliJ IDEA 乱码:全网最全 4 种方法完美解决 IntelliJ IDEA 控制台中文乱码问题

    文章目录 前言 一.修改当前 Web 项目 Tomcat Server 的虚拟机输出选项 二.修改 IntelliJ IDEA 全局编码.项目编码.属性文件编码 三.IntelliJ IDEA 中自定 ...

  2. android ppt 转图片显示不全,PPT转PDF图片显示不全怎么办?如何完美解决PPT转PDF文件?...

    原标题:PPT转PDF图片显示不全怎么办?如何完美解决PPT转PDF文件? 记得以前上学的时候,我们班级每周都会做一次小组作业汇报.每一个小组都会准备一个PPT来进行展示演讲,可是有的同学的PPT在老 ...

  3. aspose-words-15.8.0 完美解决word转pdf

    aspose-words-15.8.0 完美解决word转pdf 1.写在前面 2.集成aspose-words 3.核心的一步,是时候让word转pdf了! 4.打包会遇到的一点小坑 1.写在前面 ...

  4. 【完美解决:绝对路径含中文问题】bat一键启动应用绝对路径中含中文导致无法执行

    目录 问题由来 本篇文章将介绍: ①.bat文件如何写 ②代码每一步骤的解释 ③因电脑绝对路径中含有中文导致.bat文件无法启动的问题. .bat文件书写 .bat代码解释 .bat启动路径含中文报错 ...

  5. 完美解决ExtJs6上传中文文件名乱码,后端SpringMVC

    ExtJs上传中文文件名乱码,观察请求. ExtJs6上传乱码从后台无法解决,因为文件名请求里面就已经乱码了,后台无法解码. 除非请求参数正确没有乱码,后台因为编码设置不一样,可以通过后台处理乱码 这 ...

  6. 解决ubuntu下pdf中文不显示或乱码问题

    Ubuntu10.04终于来了,鄙人认为10.04是一个堪称完美的linux.赞一个--!使用的过程中,在阅读pdf时发现中文不显示或有乱码出现的现象.特将方解决方法记下,以备忘.方法如下.      ...

  7. 怎样将英文html文件转换成中文乱码,解决html导出pdf中文乱码问题的正确姿势

    简介 jspdf是歪果仁开发的,因此在一开始就没想过支持非英文以外的文字,这就导致了非英文的文本都是乱码. 因此就有其他大佬给增加了其他解决方案,到了1.5版本也正式加入了非英文支持的解决方案. 解决 ...

  8. html转换pdf中文失败,解决html导出pdf中文乱码问题的正确姿势

    简介 jspd页求是解这如前总回随4泉标使幻近面的是,f是歪果仁开发的,因此在一开始就没想过支持非英文以外的文字,这就导致了非英文的文本朋不功事做时次功好来多这开制的请一例农在个屏器随的会满和满时波实 ...

  9. html转换成pdf后乱码,解决html导出pdf中文乱码问题的正确姿式

    简介 本文使用jspdf 1.5.3版.GitHub地址:https://github.com/MrRio/jsPDFhtml jspdf是歪果仁开发的,所以在一开始就没想过支持非英文之外的文字,这就 ...

最新文章

  1. 在java中建个jsp文件_第一个jsp页面
  2. xhr如何发送post请求_js实现ajax的post请求步骤
  3. python处理xml文件_Python解析并修改XML文件
  4. java nio改造io,java – 将NIO与IO混合
  5. Oh my God, Swagger API文档竟然可以这样写?
  6. 实战:ajax带参数请求slim API
  7. docker rabbitmq:3.9.10-management
  8. 微软官方工具_时隔20年再出发!微软官方推出最强Windows工具集
  9. 能大大提升工作效率和时间效率的9个重要习惯
  10. js中如何解决跨域问题
  11. Web开发框架——Zheng
  12. 教我简单学计算机初步,零基础教你用电脑:常用简单操作介绍
  13. case when then else end 语句遇上sum或count等统计函数的注意事项(列转行)
  14. Leap Motion 之Unity 开发指南(一. 基本概念与制作手预制件)
  15. 在visi_Visi如何使用Weave和Docker
  16. Flask智能图书推荐系统
  17. ubantu20切换源
  18. python 挂起_Python Killing挂起函数
  19. 3dmax插件开发环境配置及FileExport和Utilities模板测试
  20. 朴素贝叶斯分类算法python实现

热门文章

  1. Eclipse jar包打不进apk
  2. Linux中ELF格式 可执行文件+动态链接器 的加载
  3. 显卡之显卡型号及版本级别
  4. Vue的常用指令(v-html {{}}文本插值,v-bind绑定属性,v-if条件渲染,v-for列表渲染,v-on @ 事件绑定,v-model表单绑定)
  5. 网络流 增广路 回退
  6. 每日求一录~20170704
  7. 洛谷 P2046 BZOJ 2007 海拔(NOI2010)
  8. setTimeout 和 setInterval
  9. 快速附加没有日志文件的 SQL Server 数据库文件!
  10. [2018/11/14]关于学习的思考