• 使用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

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

    代码部分

    HomeController.cs :

    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<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   
    
    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>Documenttitle>
        @{
            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.Emailspan>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>  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-2271351strong>p>
                <p id="fax">传真<br><strong>+91-532-25453441strong>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="#">+ Add newa>
                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();
    

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

    作者:百宝门-明维

    原文地址:https://blog.baibaomen.com/97-2/

  • 相关阅读:
    默认为4G网络
    Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析
    python函数
    mov格式如何转换成mp4?详细步骤教程
    我把皮小浪の的 蓝色妖姬系列做进了java窗口
    【操作系统】操作系统基础必知必会
    【mysql】2006 - Server has gone away
    【Mycat1.6】缓存不生效问题处理
    Request和Response
    基于知识图谱建模、全文检索的智能知识管理库(源码)
  • 原文地址:https://www.cnblogs.com/baibaomen-org/p/17238845.html