.Net Core 导出Html到PDF
阅读原文时间:2023年07月10日阅读:1

  最近由于项目的需求问题,涉及到了在.Net Core中导出PDF的一个问题,最后选择方式是后端拼接到Html页面然后再通过Html导出到PDF。中间也尝试了许多的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

  还有一些其他的没有列举出来,但是部分都是收费的,而且还有部分都是需要依赖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 = ;   //上下左右边距设置  
        Renderer.Options.MarginBottom = ;  
        Renderer.Options.MarginLeft = ;  
        Renderer.Options.MarginRight = ;

        //设置更多额参数可以去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 = )  
    {  
        //测试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 = ; j < PageSize; j++)  
        {  
            HtmlToPdf Renderer = new HtmlToPdf();  
            //设置Pdf参数  
            Renderer.Options.PdfPageOrientation = PdfPageOrientation.Landscape;//设置页面方式-横向  PdfPageOrientation.Portrait  竖向  
            Renderer.Options.PdfPageSize = PdfPageSize.A4;//设置页面大小,30种页面大小可以选择  
            Renderer.Options.MarginTop = ;   //上下左右边距设置  
            Renderer.Options.MarginBottom = ;  
            Renderer.Options.MarginLeft = ;  
            Renderer.Options.MarginRight = ;  
            //设置更多额参数可以去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;  
    } 

  整个项目Git地址


世界上那些最容易的事情中,拖延时间最不费力。坚韧是成功的一大要素,只要在门上敲得够久够大声,终会把人唤醒的。

欢迎大家扫描下方二维码,和我一起学习更多的知识