正文
现在有许多将HTML导出PDF的第三方包,这里介绍使用的是Select.HtmlToPdf.NetCore
使用Select.HtmlToPdf.NetCore
- 整体思路是将cshtml内容读出来,然后再转为Pdf文档
- 读取cshtml内容有两种方法,第一种使用第三方包
RazorEngine.NetCore
,第二种使用官方方法进行读取。(注意两种方法的cshtml内容略有不同)
效果图展示
我把所有的源代码都上传到了我的个人Github,有需要的请自取:github.com/WeiMing0803…
首先使用ChatGPT生成个人简历信息
代码部分
HomeController.cs :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public async Task ToPdf() { PdfDocument pdfDocument = new PdfDocument(); HtmlToPdf converter = new HtmlToPdf(); //实例化一个html到pdf转换器对象 converter.Options.PdfPageOrientation = PdfPageOrientation.Portrait; //设置页面方向 converter.Options.PdfPageSize = PdfPageSize.A4; //设置页面大小 converter.Options.MarginTop = 10; //设置页边距 converter.Options.MarginBottom = 10; converter.Options.MarginLeft = 10; converter.Options.MarginRight = 10; PdfReportModel model = new PdfReportModel { Name = "彭于晏" , Email = "pengyuyan@outlook.com" }; //string htmlResult = readByEngineRazor(model);//第一种方法,使用RazorEngine.NetCore读取Cshtml文件 string htmlResult = await readCshtml(model); //第二种方法 if (! string .IsNullOrEmpty(htmlResult)) { pdfDocument = converter.ConvertHtmlString(htmlResult); } string savePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), $ @"ExportPDF{DateTime.Now.ToString(" yyyyMMdd ")}" ); Directory.CreateDirectory(savePath); string filename = Path.Combine(savePath, $ "{DateTime.Now.ToString(" yyyyMMddHHmmssffff ")}.pdf" ); pdfDocument.Save(filename); byte [] bytes = System.IO.File.ReadAllBytes(filename); return File(bytes, "application/pdf" , Path.GetFileName(filename)); } private string readByEngineRazor(PdfReportModel model) { string template = System.IO.File.ReadAllText( "Views/Report/PdfReport.cshtml" ); string htmlResult = Engine.Razor.RunCompile(template, "PdfReport" , typeof (PdfReportModel), model); return htmlResult; } private async Task readCshtml(PdfReportModel model) { string htmlResult = await _viewRenderService.RenderToStringAsync( "Report/PdfReport" , model); return htmlResult; } |
TemplateGadgetProvider.cs :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class TemplateGadgetProvider { public static TemplateGadgetProvider _instance; public static TemplateGadgetProvider Instance { get { if (_instance == null ) _instance = new TemplateGadgetProvider(); return _instance; } } public string Load( string virtualPath) { return File.ReadAllText(virtualPath); } } |
pdfReport.css :
Css样式文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | html { font-family : 'Open Sans' , sans-serif ; background : whitesmoke; } a { text-decoration : none ; color : black ; } hr { background : grey; } #container { position : relative ; display : flex ; } #profile { flex : 15% ; display : block ; position : relative ; margin : 5% 2% 0 10% ; width : 100% ; height : 100% ; } #info-cards { flex : 55% ; display : block ; margin-top : 5% ; margin-right : 10% ; width : 100% ; height : 100% ; } #image { position : relative ; overflow : hidden ; } #image, #profile-photo { position : relative ; width : 80px ; height : 80px ; border-radius : 10px ; } #image > a { position : absolute ; top : 0 ; left : 0 ; background : rgba ( 0 , 0 , 0 , 0.5 ) !important ; height : 100% ; width : 100% ; display : none ; } #image > a > i { -webkit-text-stroke: 1px #ffffff dd; padding : 40% ; } #image:hover a { display : block ; } #name { font-size : 23px !important ; line-height : 20px !important ; } #about, .card > ul > li { padding : 0 0 0 15px ; position : relative ; display : inline-block ; width : 100% ; } #about { font-size : 20px !important ; padding : 0 !important ; } #name, #about > p { font-weight : bolder ; font-family : 'Open Sans' , sans-serif ; } #email { font-size : 15px !important ; font-weight : bold !important ; font-family : 'Cutive Mono' , monospace ; } #college, #email, #year-graduation, #education, #more-about, #telephone, #fax { color : #555 ; font-size : 13.5px ; } strong, span { color : black ; font-size : 16px ; } #social-links, #about { display : inline-block ; } #social-links { margin-bottom : 12px ; } #social-links a { margin : 0 10px ; } #edit-intro { display : block ; color : #097bbf ; font-family : 'Nunito' , sans-serif ; } .fab { font-size : 1.1em ; } .fab, .fas { color : whitesmoke; } #about > a { top : 4px ; right : 8px ; } .edit { top : 19px ; right : 10px ; } #about > a, .edit { position : absolute ; font-size : 15px !important ; } .stroke- transparent { -webkit-text-stroke: 1px #000 ; -webkit-text-fill- color : transparent ; } . blue { color : #097bbf !important ; font-size : 13px ; } .stroke-transparent- blue { -webkit-text-stroke: 1px #097bbf ; -webkit-text-fill- color : transparent ; } .card { box-shadow : 0 3px 10px 0 rgba ( 0 , 0 , 0 , . 1 ); overflow-x : hidden ; margin-bottom : 30px ; padding : 15px 30px 30px 30px ; background-color : #fff ; } .card > p { color : #0e141e ; font-weight : bolder ; font-size : 18px ; line-height : 2 ; } .card > p > i { font-size : 18px ; } .card > a { font-weight : 400 ; font-size : 15px ; margin : 0 ; margin-left : 25px ; padding : 0 ; border : 0 ; height : auto ; background : transparent ; color : #097bbf ; outline : none ; cursor : pointer ; } .card > ul { list-style-type : none ; } .tags { font-size : 17px ; font-weight : bolder ; } .tags ~ a { display : none !important ; } .tags span { font-size : 14px ; font-weight : normal ; color : #0e141e ; } .tags span span { color : #738f93 ; } @media screen and ( max-width : 1090px ) { #profile { margin-left : 5% ; } } @media screen and ( max-width : 850px ) { #container { display : block ; } #profile { width : 90% ; } .card { margin : 0 5% ; margin-bottom : 30px ; } } |
PdfReport.cshtml :
使用
RazorEngine.NetCore
需要修改下面两处地方删除
@model PdfReportModel
将
@Html.Raw(@style)
修改为@@Raw(@style)
视图文件:点击查看详细内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | @ using exportPdf.common @model PdfReportModel <title>Document</title> @{ string style = TemplateGadgetProvider.Instance.Load( @"wwwrootcsspdfReport.css" ); } @Html.Raw(@style)<div id= "inner-nav" ></div> <div id= "container" > <div id= "profile" > <div id= "image" > <img decoding= "async" src= "https://www.2it.club/wp-content/uploads/2023/05/frc-11c29662e65b8c4c90c5c00efc6a4ae5.jpg" ><a href= "#" rel= "external nofollow" ><i class = "fas fa-pen stroke-transparent" ></i></a> </div> <p id= "name" >@Model.Name<br><span id= "email" >@Model.Email</span></p> <p id= "designation" >前端开发工程师<br><span id= "college" >天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为也,所以动心忍性,增益其所不能。——《孟子》 </span></p> <div id= "social-links" > <a href= "#" rel= "external nofollow" ><i class = "fab fa-facebook-f stroke-transparent" ></i></a><a><i class = "fab fa-twitter stroke-transparent" ></i></a><a><i class = "fab fa-linkedin-in stroke-transparent" ></i></a><a><i class = "fab fa-github stroke-transparent" ></i></a> </div> <a id= "edit-intro" href= "#" rel= "external nofollow" ><i class = "fas fa-pen-alt blue" ></i> </a> <hr width= "100%" > <div id= "about" > <p>个人详情</p> <a href= "#" rel= "external nofollow" ><i class = "fas fa-pen stroke-transparent-blue" ></i></a> </div> <p id= "year-graduation" >预计毕业年份<br><strong>2023年6月</strong></p> <p id= "education" >学历<br><strong>湖南大学 本科</strong></p> <p id= "more-about" >专业<br><strong> 计算机科学与技术专业</strong></p> <p id= "telephone" >电话<br><strong>0532-2271351</strong></p> <p id= "fax" >传真<br><strong>+91-532-25453441</strong></p> </div> <div id= "info-cards" > <div class = "card" > <p><i class = "fas fa-briefcase stroke-transparent" ></i> 专业技能</p> <ul> <li> <p class = "tags" >1. 熟练掌握HTML、CSS、JavaScript等前端基础技术</p> </li> <li> <p class = "tags" >2. 熟悉jQuery、Bootstrap等常用前端框架和库</p> </li> <li> <p class = "tags" >3. 了解Node.js、Express等后端开发技术</p> </li> <li> <p class = "tags" >4. 掌握Git、Webpack等常用开发工具</p> </li> <li> <p class = "tags" >5. 具备良好的编码风格和文档习惯</p> </li> </ul> </div> <div class = "card" > <p><i class = "fas fa-briefcase stroke-transparent" ></i> 工作检验</p> <ul> <li> <p class = "tags" >1. 依帆网站首页制作(个人项目)<br> - 使用HTML、CSS、JavaScript实现了一个响应式的网站首页<br> - 使用Bootstrap进行布局和样式美化,使用jQuery实现轮播图和导航栏效果<br> - 使用Webpack进行打包和优化,使用Git进行版本控制和部署</p> </li> <li> <p class = "tags" >2. 艺风网站后台管理系统(实习项目)<br> - 参与了一个基于Node.js和Express的后台管理系统的开发<br> - 负责前端页面的编写,使用EJS模板引擎渲染数据<br> - 使用Ajax和Fetch进行数据交互,使用Element UI组件库提升用户体验<br> - 遵循MVC架构,使用Mongoose操作MongoDB数据库</p> </li> </ul> </div> <div class = "card" > <p><i class = "fas fa-graduation-cap stroke-transparent" ></i> 自我评价</p> <ul> <li> <p class = "tags" >具备较强的学习能力和逻辑思维能力,喜欢接触新技术和新知识</p> </li> <li> <p class = "tags" >具备良好的沟通能力和团队协作能力,能够积极配合团队完成任务</p> </li> <li> <p class = "tags" >具备一定的创新能力和解决问题能力,能够针对不同需求提出合理方案</p> </li> </ul> <a href= "#" rel= "external nofollow" >+ Add new </a> </div> </div> </div> |
ViewRenderService :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | public class ViewRenderService { private readonly IRazorViewEngine _razorViewEngine; private readonly ITempDataProvider _tempDataProvider; private readonly IServiceProvider _serviceProvider; public ViewRenderService(IRazorViewEngine razorViewEngine, ITempDataProvider tempDataProvider, IServiceProvider serviceProvider) { _razorViewEngine = razorViewEngine; _tempDataProvider = tempDataProvider; _serviceProvider = serviceProvider; } public async Task< string > RenderToStringAsync( string viewName, object model) { var httpContext = new DefaultHttpContext { RequestServices = _serviceProvider }; var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor()); using ( var sw = new StringWriter()) { var viewResult = _razorViewEngine.FindView(actionContext, viewName, false ); if (viewResult.View == null ) { throw new ArgumentNullException($ "{viewName} does not match any available view" ); } var viewDictionary = new ViewDataDictionary( new EmptyModelMetadataProvider(), new ModelStateDictionary()) { Model = model }; var viewContext = new ViewContext( actionContext, viewResult.View, viewDictionary, new TempDataDictionary(actionContext.HttpContext, _tempDataProvider), sw, new HtmlHelperOptions() ); await viewResult.View.RenderAsync(viewContext); return sw.ToString(); } } } |
Program.cs :
1 | builder.Services.AddTransient(); |
以上就是使用Select.HtmlToPdf.NetCore
将HTML导出为PDF的全部内容!
更多关于Net HTML导出为PDF格式的资料请关注IT俱乐部其它相关文章!