.Net Core 導出Html到PDF

  • 2020 年 1 月 31 日
  • 筆記

前言

  最近由於項目的需求問題,涉及到了在.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;          } 

整個項目Git地址


 世界上那些最容易的事情中,拖延時間最不費力。堅韌是成功的一大要素,只要在門上敲得夠久夠大聲,終會把人喚醒的。