使用.Net将HTML简历导出为PDF格式

现在有许多将HTML导出PDF的第三方包,这里介绍使用的是Select.HtmlToPdf.NetCore

使用Select.HtmlToPdf.NetCore

  1. 整体思路是将cshtml内容读出来,然后再转为Pdf文档

  2. 读取cshtml内容有两种方法,第一种使用第三方包 RazorEngine.NetCore,第二种使用官方方法进行读取。(注意两种方法的cshtml内容略有不同).

效果图展示

我把所有的源代码都上传到了我的个人Github,有需要的请自取:https://github.com/WeiMing0803/ExportPdf

使用.Net将HTML简历导出为PDF格式

首先使用ChatGPT生成个人简历信息

使用.Net将HTML简历导出为PDF格式

代码部分

HomeController.cs :


 
public async Task<IActionResult> 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<string> readCshtml(PdfReportModel model){    string htmlResult = await _viewRenderService.RenderToStringAsync("Report/PdfReport", model);    return htmlResult;}

TemplateGadgetProvider.cs :


 
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样式文件:点击查看详细内容


 
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 #ffffffdd;            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需要修改下面两处地方

  1. 删除 @model PdfReportModel

  2. @Html.Raw(@style) 修改为 @@Raw(@style)

视图文件:


 
@using exportPdf.common@model PdfReportModel   
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta http-equiv="X-UA-Compatible" content="IE=edge">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <title>Document</title>    @{        string style = TemplateGadgetProvider.Instance.Load(@"wwwroot\css\pdfReport.css");    }    <style>@Html.Raw(@style)</style></head>
<body>    <div id="inner-nav"></div>    <div id="container">        <div id="profile">            <div id="image">                <img id="profile-photo" src="https://img2023.cnblogs.com/blog/233608/202303/233608-20230308165653594-2049775608.jpg" alt="Profile-Image">                <a href="#"><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="#"><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="#"><i class="fas fa-pen-alt blue"></i>&nbsp;&nbsp;</a>            <hr width="100%">            <div id="about">                <p style="display:inline;">个人详情</p>                <a href="#"><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>&nbsp;&nbsp;&nbsp;专业技能</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>&nbsp;&nbsp;&nbsp;工作检验</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>&nbsp;&nbsp;&nbsp;自我评价</p>                <ul>                    <li>                        <p class="tags">具备较强的学习能力和逻辑思维能力,喜欢接触新技术和新知识</p>                    </li>                    <li>                        <p class="tags">具备良好的沟通能力和团队协作能力,能够积极配合团队完成任务</p>                    </li>                    <li>                        <p class="tags">具备一定的创新能力和解决问题能力,能够针对不同需求提出合理方案</p>                    </li>                </ul>                <a href="#">+ Add new</a>            </div>        </div>    </div></body></html>

ViewRenderService :


 
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 :
builder.Services.AddTransient<ViewRenderService>();

以上就是使用Select.HtmlToPdf.NetCore将HTML导出为PDF的全部内容!