最近领导给了一个新的需求:给了我一个html页面,让我导出Pdf页面
由于以前没有搞过这方面的需求,所以查百度找资料,找了一大堆的好东西,像ItextSharp和wkhtmltopdf
废话不说,进入正题
ItextSharp对Html5的canvas和css,js等支持不是很好,只适用于简单的页面导出。故放弃
导出方法一:使用wkhtmltopdf
这个需要安装wkhtmltopdf: https://wkhtmltopdf.org/downloads.html 下面的变量就是wkhtmltopdf的安装目录
public ActionResult ExportSocialPDF(int testerid)
{
try
{
var tester = _testerBll.Details(testerid);
string folder = string.Format("~/Temp/{0}", DateTime.Now.ToString("yyyyMMdd"));
if (!System.IO.Directory.Exists(Server.MapPath(folder)))
{
System.IO.Directory.CreateDirectory(Server.MapPath(folder));
}
string fileName = string.Format("{0}-社会综合素质测试{1}", tester.name, DateTime.Now.ToString("yyyyMMddHHmmss"));
string pdfpath = fileName + ".pdf";
ExportSocialPDFCore(tester, folder, pdfpath);
string filePath = Server.MapPath(folder) + "/" + pdfpath;
new System.Threading.Thread(DeleteOldFileFolder).Start();
return File(filePath, "application/octet-stream", System.IO.Path.GetFileName(filePath));
}
catch (Exception ex)
{
log.Error(ex);
return View(ex);
}
}
public void ExportSocialPDFCore(HqftTestPaper.Entity.t_testerEntity tester, string folder, string pdfpath)
{
string pdf = @"C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe";
//string url = "http://localhost/TestManage/WordTemplate/index.html";
string url = Url.Action("ExportPreview", "ExportPDF", new { testerid = tester.id }); url = string.Format("http://{0}:{1}{2}",Request.Url.Host, Request.Url.Port, url); string add = url + " \"" + Server.MapPath(folder + "/" + pdfpath) + "\"";
Process p = System.Diagnostics.Process.Start(pdf, add);
p.WaitForExit();
}
public void DeleteOldFileFolder()
{
string strPath = Server.MapPath("~/Temp/");
string[] fileNames = System.IO.Directory.GetDirectories(strPath);
foreach (string fileName in fileNames)
{
string name = fileName.Substring(strPath.Length);
if (string.Compare(DateTime.Now.ToString("yyyyMMdd"), name) > )
{
System.IO.Directory.Delete(fileName, true);
}
}
}
注释:
1、t_testerEntity是个需要导出的测试者的类,大家可以自行脑补,只要一个id获取数据就可以了
2、此方法是现在本地生成一个Pdf,然后把路径传到View让浏览器下载,所以需要一个删除旧文件的方法
3、根据cshtml下载的页面,必须能够无限制的访问,就是直接把路径贴在浏览器中可以直接访问。
如果为了系统安全性,加了访问限制的,需要新建一个不受限制的Controller
导出方法二:页面先截图,然后生成Pdf
这个用的是Winform的WebBrowser控件,有限制:你的IE和你的WebBrowser内核可能不是一个版本的。Css支持率极低。个人认为不好用
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms; namespace ExportPDF.Common
{
public class HtmlToPdf
{
WebBrowser webBrowser; public void ConvertToImage(object url)
{
//string strUrl = "http://echarts.baidu.com/demo.html#pie-legend";
webBrowser = new WebBrowser();
//改变webBrowser内核版本
WebBrowserOper.BrowserEmulationSet();
webBrowser.AllowNavigation = true;
webBrowser.Url = new Uri(url.ToString());
webBrowser.ScrollBarsEnabled = true;
DateTime dtime = DateTime.Now;
double timespan = ;
while (timespan < || webBrowser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
DateTime time2 = DateTime.Now;
timespan = (time2 - dtime).TotalSeconds;
} if (webBrowser.ReadyState == WebBrowserReadyState.Complete)
{
//htmlstr = webBrowser.DocumentText;
webBrowser_DocumentCompleted();
}
//string html = ""; //webBrowser.DocumentText = html;
} /// <summary>
/// 在单线程中启用浏览器
/// </summary>
public void RunWithSingleThread()
{
string url = "http://localhost/Export/template/index.html";
ParameterizedThreadStart ps = new ParameterizedThreadStart(ConvertToImage);
Thread t = new Thread(ps);
t.IsBackground = true;
t.SetApartmentState(ApartmentState.STA);
t.Start(url);
} private void webBrowser_DocumentCompleted()
{
//获取解析后HTML的大小
System.Drawing.Rectangle rectangle = webBrowser.Document.Body.ScrollRectangle;
int width = rectangle.Width;
int height = rectangle.Height; //设置解析后HTML的可视区域
webBrowser.Width = width;
webBrowser.Height = height; Bitmap bitmap = new System.Drawing.Bitmap(width, height);
webBrowser.DrawToBitmap(bitmap, new System.Drawing.Rectangle(, , width, height)); //设置图片文件保存路径和图片格式,格式可以自定义
string filePath = AppDomain.CurrentDomain.BaseDirectory + "/SaveFile/" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".png";
bitmap.Save(filePath, System.Drawing.Imaging.ImageFormat.Png); //创建PDF
FileStream fileStream = new FileStream(AppDomain.CurrentDomain.BaseDirectory + "/SaveFile/" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + ".pdf", FileMode.Create); byte[] result = CreatePDF(bitmap, width, height); fileStream.Write(result, , result.Length); fileStream.Close();
fileStream.Dispose();
} private byte[] CreatePDF(Bitmap bitmap, int width, int height)
{
using (MemoryStream ms = new MemoryStream())
{
Document doc = new Document(new iTextSharp.text.Rectangle(, , width, height), , , , ); // 左右上下 PdfWriter writer = PdfWriter.GetInstance(doc, ms); writer.CloseStream = false; doc.Open(); iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(bitmap, System.Drawing.Imaging.ImageFormat.Png); img.ScalePercent(); // 放缩比例 doc.Add(img); // 添加图片对像
doc.Close(); return ms.ToArray();
}
}
}
}
using Microsoft.Win32;
using System;
using System.Diagnostics; namespace ExportPDF.Common
{
public static class WebBrowserOper
{
public static void WebBrowserVersionEmulation()
{
const string BROWSER_EMULATION_KEY = @"SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION";
//const string BROWSER_EMULATION_KEY = @"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION"; // app.exe and app.vshost.exe
RegistryKey browserEmulationKey = Registry.LocalMachine.OpenSubKey(BROWSER_EMULATION_KEY,RegistryKeyPermissionCheck.ReadWriteSubTree) ?? Registry.LocalMachine.CreateSubKey(BROWSER_EMULATION_KEY);
//RegistryKey browserEmulationKey = Registry.CurrentUser.OpenSubKey(BROWSER_EMULATION_KEY,RegistryKeyPermissionCheck.ReadWriteSubTree) ?? Registry.LocalMachine.CreateSubKey(BROWSER_EMULATION_KEY);
if (browserEmulationKey != null)
{
String appname = Process.GetCurrentProcess().ProcessName + ".exe";
//Webpages are displayed in IE10 Standards mode, regardless of the !DOCTYPE directive.
const int browserEmulationMode = ; if ((int)browserEmulationKey.GetValue(appname) != )
{
browserEmulationKey.SetValue(appname, browserEmulationMode, RegistryValueKind.DWord);
}
browserEmulationKey.Close();
}
} /// <summary>
/// IE WebBrowser内核设置
/// </summary>
public static void BrowserEmulationSet()
{
//当前程序名称
var exeName = Process.GetCurrentProcess().ProcessName + ".exe";
//系统注册表信息
var mreg = Registry.LocalMachine;
//IE注册表信息
var ie = mreg.OpenSubKey(@"SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION", RegistryKeyPermissionCheck.ReadWriteSubTree);
if (ie != null)
{
try
{
var val = ieVersionEmulation(ieVersion());
if (val != )
{
ie.SetValue(exeName, val);
}
mreg.Close();
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
}
} /// <summary>
/// IE版本号
/// </summary>
/// <returns></returns>
static int ieVersion()
{
//IE版本号
RegistryKey mreg = Registry.LocalMachine;
mreg = mreg.CreateSubKey("SOFTWARE\\Microsoft\\Internet Explorer"); //更新版本
var svcVersion = mreg.GetValue("svcVersion");
if (svcVersion != null)
{
mreg.Close();
var v = svcVersion.ToString().Split('.')[];
return int.Parse(v);
}
else
{
//默认版本
var ieVersion = mreg.GetValue("Version");
mreg.Close();
if (ieVersion != null)
{
var v = ieVersion.ToString().Split('.')[];
return int.Parse(v);
}
}
return ;
} /// <summary>
/// 根据IE版本号 返回Emulation值
/// </summary>
/// <param name="ieVersion"></param>
/// <returns></returns>
static int ieVersionEmulation(int ieVersion)
{
//IE7 7000 (0x1B58)
if (ieVersion < )
{
return ;
}
if (ieVersion == )
{
return 0x1F40;//8000 (0x1F40)、8888 (0x22B8)
}
if (ieVersion == )
{
return 0x2328;//9000 (0x2328)、9999 (0x270F)
}
else if (ieVersion == )
{
return 0x02710;//10000 (0x02710)、10001 (0x2711)
}
else if (ieVersion == )
{
return 0x2AF8;//11000 (0x2AF8)、11001 (0x2AF9
}
return ;
}
}
}
另外还有一个导出Html的
using System.IO;
using System.Text;
using System.Web; namespace ExportPDF.Common
{
public class ExportHtml
{
public void TemplateExport()
{
string templatePath = HttpContext.Current.Server.MapPath("~/Template/") + "index.html";
string template = "";
using (StreamReader sr = new StreamReader(templatePath))
{
template=sr.ReadToEnd();
}
//新的内容
StringBuilder context = new StringBuilder();
/*
foreach (Student stu in stulist)
{
context.Append("<tr>");
context.Append("<td>" + stu.XueHao + "</td><td>" + stu.XingMing + "</td>");
context.Append("</tr>");
}
string newContext = template.Replace("$student$", context.ToString());
*/
//把newContext写入报表中
string path = HttpContext.Current.Server.MapPath("~/SaveFile/") + "report.html";
using (StreamWriter sw = new StreamWriter(path, false))
{
sw.WriteLine(template);
}
}
}
}
言尽于此