ASP.NET Core html生成pdf

本文,主要记录在处理.NET Core Web API项目时使用DinkToPDF库轻松生成PDF。

本文源码 https://github.com/forestGzh/HtmlToPdf

DinkToPdf,是一个跨平台的库,是Webkit HTML to PDF库的包装。它使用WebKit引擎将HTML转换为PDF。它可以在.NET Core项目中将HTML字符串生成PDF文档,或者从现有的HTML页面创建PDF文档。

由于官方的DinkToPdf https://github.com/rdvojmoc/DinkToPdf 最新的更新已经是三年前的了,原来的DinkToPdf需要引入几个dll,这些dll也没有更新,导致目前在linux系统中,还有docker容器环境中无法使用。(github上也有很多issue都是关于这些问题的,好像都没有特别好的处理办法)。

后来发现了一个Haukcode.DinkToPdf这个库,是作者根据DinkToPdf改造的(https://www.nuget.org/packages/Haukcode.DinkToPdf/
),将一些dll整合进去了,也兼容容器环境了。

安装,在.csproj中加上下面这行,然后restore一下。或者直接去NuGet包管理器搜索安装也是一样的。

<PackageReference Include="Haukcode.DinkToPdf" Version="1.1.2" />

Install-Package Haukcode.DinkToPdf -Version 1.1.2

在Startup.cs中添加:

services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));//DinkToPdf注入

创建IPDFService

using System;
namespace HtmlToPdf.Services
{
    /// <summary>
    /// 与pdf相关
    /// </summary>
    public interface IPDFService
    {
        /// <summary>
        /// 创建PDF
        /// </summary>
        /// <param name="htmlContent">传入html字符串</param>
        /// <returns></returns>
        byte[] CreatePDF(string htmlContent);
    }
}

创建PDFService

using System;
using DinkToPdf;
using DinkToPdf.Contracts;

namespace HtmlToPdf.Services
{
    /// <summary>
    /// 与pdf相关
    /// </summary>
    public class PDFService : IPDFService
    {
        private IConverter _converter;
        public PDFService(IConverter converter)
        {
            _converter = converter;
        }

        /// <summary>
        /// 创建PDF
        /// </summary>
        /// <param name="htmlContent">传入html字符串</param>
        /// <returns></returns>
        public byte[] CreatePDF(string htmlContent)
        {
            var globalSettings = new GlobalSettings
            {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
                //Margins = new MarginSettings
                //{
                //    Top = 10,
                //    Left = 0,
                //    Right = 0,
                //},
                DocumentTitle = "PDF Report",
            };

            var objectSettings = new ObjectSettings
            {
                PagesCount = true,
                HtmlContent = htmlContent,
                // Page = "www.baidu.com", //USE THIS PROPERTY TO GENERATE PDF CONTENT FROM AN HTML PAGE  这里是用现有的网页生成PDF
                //WebSettings = { DefaultEncoding = "utf-8", UserStyleSheet = Path.Combine(Directory.GetCurrentDirectory(), "assets", "styles.css") },
                WebSettings = { DefaultEncoding = "utf-8" },
                //HeaderSettings = { FontName = "Arial", FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
                //FooterSettings = { FontName = "Arial", FontSize = 9, Line = true, Center = "Report Footer" }
            };

            var pdf = new HtmlToPdfDocument()
            {
                GlobalSettings = globalSettings,
                Objects = { objectSettings }
            };

            var file = _converter.Convert(pdf);

            //return File(file, "application/pdf");

            return file;

        }
    }
}

在Startup.cs中依赖注入:

services.AddTransient<IPDFService, PDFService>();

创建TemplateGenerator,生成html字符串

using System;
using System.Text;

namespace HtmlToPdf
{
    public static class TemplateGenerator
    {
        /// <summary>
        /// 获取HTML字符串
        /// </summary>
        /// <returns></returns>
        public static string GetPDFHTMLString()
        {

            StringBuilder sb = new StringBuilder();

            sb.Append(@"
<html>
  <head>
    <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
    <style>
      
    </style>
  </head>

  <body>
    <div>
        这是一个网页!
    </div>
  </body>
</html>
            ");

            return sb.ToString();
        }
    }
}

修改ValuesController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using HtmlToPdf.Services;
using Microsoft.AspNetCore.Mvc;

namespace HtmlToPdf.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ValuesController : ControllerBase
    {
        private IPDFService _PDFService;

        public ValuesController(IPDFService pDFService)
        {
            _PDFService = pDFService;
        }

        [HttpGet("pdf")]
        public FileResult GetPDF()
        {
            //获取html模板
            var htmlContent = TemplateGenerator.GetPDFHTMLString();

            //生成PDF
            var pdfBytes = _PDFService.CreatePDF(htmlContent);

            return File(pdfBytes, "application/pdf");
        }
    }
}

测试:
浏览器输入 https://localhost:5001/api/values/pdf

image.png

可以看到html字符串已经生成了pdf文档

本文项目部署的环境是在Docker容器中,采用ASP.NET Core官方的镜像。
这个镜像是精简的,所以没有一些字体,那就这样部署到docker容器中的话网页会乱码。
所以,要手动添加字体。如下,下载字体文件simsun.ttc。
在dockerfile文件中添加:

ADD ./simsun.ttc /usr/share/fonts/simsun.ttc

构建镜像部署即可

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,539评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,594评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,871评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,963评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,984评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,763评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,468评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,850评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,002评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,144评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,823评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,483评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,026评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,150评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,415评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,092评论 2 355

推荐阅读更多精彩内容