.Net Core 导出Html到PDF
前言
最近由于项目的需求问题,涉及到了在.Net Core中导出PDF的一个问题,最后选择方式是后端拼接到Html页面然后再通过Html导出到PDF。中间也尝试了许多的NuGet包、但是并不如意,可用并且好用的的比较少。下面将最近最几天尝试的使用方法分享给大家。
NuGet包
Select.HtmlToPdf.NetCore 简单好用,缺点是仅支持Windows,部署Linux不支持
HtmlToPDFCore 免费 支持Windows Linux 但是功能简单,样式不稳定
PdfSharpCore Html内容转PDF较为麻烦
DinkToPdf 依赖wkhtmltopdf,需要附带exe应用程序
iTextSharp 5.0以后的收费了,而且NuGet包最低都在5.0以上,也就是收费
iTextSharp.LGPLv2.Core Html内容转PDF太复杂
PDF.Core 收费
HTML-Renderer.Core 较久没有维护支持,不兼容
HTML-Renderer.PdfSharp 可以使用但是不兼容Core
Spire.PDF 收费
ExpertPdf.HtmlToPdf.NetCore 收费
hiqpdf.free 免费不兼容Core
Select.HtmlToPdf.NetCore 操作案例
还有一些其他的没有列举出来,但是部分都是收费的,而且还有部分都是需要依赖wkhtmltopdf做PDF导出,最后尝试使用的还是Select.HtmlToPdf.NetCore 。但是也仅限在Windows平台。但是使用确实比较方便。我们看下具体操作:
首先安装Select.HtmlToPdf.NetCore NuGet包
我们首先看下简单的一个Html内容和Url导出为PDF文件的例子:
//获取项目路径使用
IHostingEnvironment hostingEnv;
public ValuesController(IHostingEnvironment hostingEnv)
{
this.hostingEnv = hostingEnv;
}
/// <summary>
/// Html导出PDF
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
//测试Html素材
string htmlString = @"<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title></title>
<style>
body {
margin: 0;
padding: 0;
min-width: 2000px;
}
.m_table {
border-collapse: separate;
margin: 100px auto 0;
min-width: 1900px;
text-align: center;
font: 500 17px '微软雅黑';
border-spacing: 0;
border: 1px solid #EBEEF5;
}
.m_table th {
background-color: #F7F3F7;
}
.m_table th,
.m_table td {
border-right: 1px solid #EBEEF5;
border-bottom: 1px solid #EBEEF5;
padding: 5px;
height: 60px;
width: 60px;
}
</style>
</head>
<body>
<table class='m_table'>
<tr>
<th colspan='9' style='text-align:center;font-size:28px;'>期末学生综合评价表1</th>
</tr>
<tr>
<th colspan='9' style='text-align:center;font-size:23px;'>班级:一年级一班 姓名:测试 班主任:测试</th>
</tr>
<tr>
<th rowspan='2' style='text-align:center;font-size:24px;'>学科</th>
<th colspan='2' rowspan='2' style='text-align:center;font-size:24px;'>过程性评价</th>
<th colspan='2' rowspan='2' style='text-align:center;font-size:24px;'>表现性评价</th>
<th colspan='2' style='text-align:center;font-size:20px;'>考试性评价</th>
<th colspan='2' style='text-align:center;font-size:20px;'>综合性评价</th>
</tr>
<tr>
<th style='text-align:center;font-size:18px;'>卷面分</th>
<th style='text-align:center;font-size:18px;'>权重分</th>
<th style='text-align:center;font-size:18px;'>总分</th>
<th style='text-align:center;font-size:18px;'>等级</th>
</tr>
<tr><td> 数学 </td><td> 作业评价/4 </td><td> 课堂表现/4 </td><td> 学科必选/10 </td><td> 学科自选/7 </td><td> 98 </td><td> 68.6 </td><td> 93.6 </td><td> A </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr>
</table>
</body>
</html>";
HtmlToPdf Renderer = new HtmlToPdf();
//设置Pdf参数
Renderer.Options.PdfPageOrientation = PdfPageOrientation.Landscape;//设置页面方式-横向 PdfPageOrientation.Portrait 竖向
Renderer.Options.PdfPageSize = PdfPageSize.A4;//设置页面大小,30种页面大小可以选择
Renderer.Options.MarginTop = 10; //上下左右边距设置
Renderer.Options.MarginBottom = 10;
Renderer.Options.MarginLeft = 10;
Renderer.Options.MarginRight = 10;
//设置更多额参数可以去HtmlToPdfOptions里面选择设置
var docHtml = Renderer.ConvertHtmlString(htmlString);//根据html内容导出PDF
var docUrl = Renderer.ConvertUrl("https://fanyi.baidu.com/#en/zh/");//根据url路径导出PDF
string webRootPath = hostingEnv.ContentRootPath; //获取项目运行绝对路径
var path = $"/ExportPDF/{DateTime.Now.ToString("yyyyMMdd")}/";//文件相对路径
var savepathHtml = $"{webRootPath}{path}{Guid.NewGuid().ToString()}-Html.pdf";//保存绝对路径
if (!Directory.Exists(Path.GetDirectoryName(webRootPath + path)))
{
Directory.CreateDirectory(Path.GetDirectoryName(webRootPath + path));
}
docHtml.Save(savepathHtml);
var savepathUrl = $"{webRootPath}{path}{Guid.NewGuid().ToString()}-Url.pdf";//保存绝对路径
docUrl.Save(savepathUrl);
return new string[] { savepathHtml, savepathUrl };
}
下面我们看Html内容导出一个PDF文件多个页面的例子:
/// <summary> /// Html导出PDF一个文件多页 /// </summary> /// <param name="PageSize"></param> /// <returns></returns> [HttpGet("HtmlToPdfList")] public ActionResult<string> HtmlToPdfList(int PageSize = 1) { //测试Html素材 string htmlString = @"<!DOCTYPE html> <html> <head> <meta charset='utf-8' /> <title></title> <style> body { margin: 0; padding: 0; min-width: 2000px; } .m_table { border-collapse: separate; margin: 100px auto 0; min-width: 1900px; text-align: center; font: 500 17px '微软雅黑'; border-spacing: 0; border: 1px solid #EBEEF5; } .m_table th { background-color: #F7F3F7; } .m_table th, .m_table td { border-right: 1px solid #EBEEF5; border-bottom: 1px solid #EBEEF5; padding: 5px; height: 60px; width: 60px; } </style> </head> <body> <table class='m_table'> <tr> <th colspan='9' style='text-align:center;font-size:28px;'>期末学生综合评价表1</th> </tr> <tr> <th colspan='9' style='text-align:center;font-size:23px;'>班级:一年级一班 姓名:测试 班主任:测试</th> </tr> <tr> <th rowspan='2' style='text-align:center;font-size:24px;'>学科</th> <th colspan='2' rowspan='2' style='text-align:center;font-size:24px;'>过程性评价</th> <th colspan='2' rowspan='2' style='text-align:center;font-size:24px;'>表现性评价</th> <th colspan='2' style='text-align:center;font-size:20px;'>考试性评价</th> <th colspan='2' style='text-align:center;font-size:20px;'>综合性评价</th> </tr> <tr> <th style='text-align:center;font-size:18px;'>卷面分</th> <th style='text-align:center;font-size:18px;'>权重分</th> <th style='text-align:center;font-size:18px;'>总分</th> <th style='text-align:center;font-size:18px;'>等级</th> </tr> <tr><td> 数学 </td><td> 作业评价/4 </td><td> 课堂表现/4 </td><td> 学科必选/10 </td><td> 学科自选/7 </td><td> 98 </td><td> 68.6 </td><td> 93.6 </td><td> A </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr><tr><td> 英语 </td><td> 作业评价/4.5 </td><td> 课堂表现/5 </td><td> 学科必选/1.7 </td><td> 学科自选/1.7 </td><td> 59 </td><td> 41.3 </td><td> 54.2 </td><td> D </td></tr> </table> </body> </html>"; PdfDocument docHtml = null; for (int j = 0; j < PageSize; j++) { HtmlToPdf Renderer = new HtmlToPdf(); //设置Pdf参数 Renderer.Options.PdfPageOrientation = PdfPageOrientation.Landscape;//设置页面方式-横向 PdfPageOrientation.Portrait 竖向 Renderer.Options.PdfPageSize = PdfPageSize.A4;//设置页面大小,30种页面大小可以选择 Renderer.Options.MarginTop = 10; //上下左右边距设置 Renderer.Options.MarginBottom = 10; Renderer.Options.MarginLeft = 10; Renderer.Options.MarginRight = 10; //设置更多额参数可以去HtmlToPdfOptions里面选择设置 if (docHtml == null) docHtml = Renderer.ConvertHtmlString(htmlString);//根据html内容导出PDF else //在上一个pdf元素页面下面追加Pdf页面,官方文档对于一个pdf文件打印多页的处理提供了分页符,在你想打印一页的元素外面加上 <div style="font-size: 28px; page-break-after: always">元素 //也就是分页符,但是试用感觉效果并不理想,下面这个Append追加一个pdf页面效果会更好点,但是可能会损耗一些性能 docHtml.Append(Renderer.ConvertHtmlString(htmlString)); } string webRootPath = hostingEnv.ContentRootPath; //获取项目运行绝对路径 var path = $"/ExportPDF/{DateTime.Now.ToString("yyyyMMdd")}/";//文件相对路径 var savepathHtml = $"{webRootPath}{path}{Guid.NewGuid().ToString()}-Html.pdf";//保存绝对路径 if (!Directory.Exists(Path.GetDirectoryName(webRootPath + path))) { Directory.CreateDirectory(Path.GetDirectoryName(webRootPath + path)); } docHtml.Save(savepathHtml); return savepathHtml; }
世界上那些最容易的事情中,拖延时间最不费力。坚韧是成功的一大要素,只要在门上敲得够久够大声,终会把人唤醒的。
欢迎大家扫描下方二维码,和我一起学习更多的知识😊