LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

通过代码实现 PDF文件自动盖章

freeflydom
2024年7月22日 11:40 本文热度 652

序言

在数字化时代,电子文档的安全性和真实性越来越受到重视。电子印章作为一种数字化的身份验证工具,已经成为确保文档合法性和不可篡改性的重要手段。然而,传统的电子印章往往需要人工操作,不仅效率低下,而且在处理大量文件时容易出错。为了解决这一问题,自动化地给PDF文件盖电子章成为了一个迫切的需求。本文将详细介绍,如何通过 .net 程序实现这一功能,废话不多说,步入正题

Nuget 包

本文的核心包为:

  • iTextSharp,用它来操作 pdf 文件非常方便,具体的用法这里不多赘述,请参考官网

  • DynamicExpresso,一个非常好用的动态表达式解析工具包

<ItemGroup>

  <PackageReference Include="DynamicExpresso.Core" Version="2.16.1" />

  <PackageReference Include="iTextSharp" Version="5.5.13.3" />

  <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />

</ItemGroup>



素材准备

本案例用到的素材包括:用于测试的 pdf 文件一个,模拟电子章图片一张,以及盖章配置文件,文件内容如下:

[

  {

    "SignType" : "image",//素材类型,image表示图片素材,text 表示文本素材

    "LastPage" : true,//是否仅最后一页盖章

    "ImageUrl" : "https://xxxxxxxx",//图片素材的下载链接

    "FileName" : "sign.png",//图片素材文件名称

    "ScalePercent" : 20,//图片缩放百分比,100 表示不缩放

    "Opacity" : 0.6,//图片透明度,1 表示不透明

    "LocationX" : "(input.Width/10)*6",//图片素材的绝对位置表达式,(0,0) 表示左下角

    "LocationY" : "input.Height/23 +20",//input.With 和 input.Height 代表 pdf 文件的宽度及高度

    "Rotation" : 0//素材的旋转角度

  },

  {

    "SignType" : "text",

    "LastPage" : true,

    "LocationX" : "(input.Width/10)*6+85",

    "LocationY" : "input.Height/23 ",

    "Rotation" : 0,

    "FontSize" : 20,

    "Opacity" : 0.6,

    "FontColor" : {//文本素材的字体颜色值

      "R" : 255,

      "G" : 0,

      "B" : 0

    },

    "Text" : "input.Date"//文本素材的表达式,也可以直接写固定文本

  }

]


说明:

  1. 这里之所以设计为一个数组,是因为可能有些场景下,不仅需要盖电子章,还需要自动签上日期,比如本案例。

  2. 签署位置可以自定义,坐标(0,0)代表的是左下角,x 变大即表示横向右移,y 变大表示纵向上移。

  3. 配置文件存储,我这里是把配置文件放在了本地,当然你可以存储在任何地方,比如 MongoDB等。

代码展示

本案例采用的是 .net7.0,当然 .net6及以后都是可以的。

  1. 配置文件类,与上一步的 json 配置文件对应

namespace PdfSign;


public class SignOpt

{

    public string SignType { get; set; }

    public bool LastPage { get; set; }

    public string ImageUrl { get; set; }

    public string FileName { get; set; }

    public int ScalePercent { get; set; } = 50;

    public string LocationX { get; set; }

    public string LocationY { get; set; }

    public float LocationYf { get; set; }

    public float Rotation { get; set; } = 0;

    public int FontSize { get; set; }

    public float Opacity { get; set; }

    public RBGColor FontColor { get; set; }

    public string? Text { get; set; }

    

    public record RBGColor(int R, int G, int B);

}


  1. pdf 签署方法

using System.Dynamic;

using DynamicExpresso;

using iTextSharp.text;

using iTextSharp.text.pdf;

using Newtonsoft.Json.Linq;


namespace PdfSign;


public class SignService

{

    public static string PdfSign(List<SignOpt> signOpts, string pdfName)

    {

        var beforeFileName = pdfName; //签名之前文件名

        var afterFileName = pdfName + "_sign"; //签名之后文件名

        var idx = 0;

        foreach (var opt in signOpts)

        {

            //创建盖章后生成pdf

            var outputPdfStream =

                new FileStream(afterFileName + ".pdf", FileMode.Create, FileAccess.Write, FileShare.None);

            //读取原有pdf

            var pdfReader = new PdfReader(beforeFileName + ".pdf");

            var pdfStamper = new PdfStamper(pdfReader, outputPdfStream);

            //读取页数

            var pdfPageSize = pdfReader.NumberOfPages;

            //读取pdf文件第一页尺寸,得到 With 和 Height

            var size = pdfReader.GetPageSize(1);

            //通过表达式计算出签署的绝对坐标

            var locationX = Eval<float>(opt.LocationX, new { size.Width, size.Height });

            var locationY = Eval<float>(opt.LocationY, new { size.Width, size.Height });


            if (opt.LastPage)

            {

                //盖章在最后一页

                var pdfContentByte = pdfStamper.GetOverContent(pdfPageSize);

                var gs = new PdfGState

                {

                    FillOpacity = opt.Opacity

                };

                pdfContentByte.SetGState(gs);

                switch (opt.SignType.ToLower())

                {

                    case "image":

                        //获取图片

                        var image = Image.GetInstance(opt.FileName);

                        //设置图片比例

                        image.ScalePercent(opt.ScalePercent);

                        //设置图片的绝对位置,位置偏移方向为:左到右,下到上

                        image.SetAbsolutePosition(locationX, locationY);

                        //图片添加到文档

                        pdfContentByte.AddImage(image);

                        break;

                    case "text":

                        if (string.IsNullOrWhiteSpace(opt.Text))

                            continue;

                        var font = BaseFont.CreateFont();

                        var text = Eval<string>(opt.Text, new { Date = DateTime.Now.ToString("yyyy-MM-dd") });

                        //开始写入文本

                        pdfContentByte.BeginText();

                        pdfContentByte.SetColorFill(

                            new BaseColor(opt.FontColor.R, opt.FontColor.G, opt.FontColor.B));

                        pdfContentByte.SetFontAndSize(font, opt.FontSize);

                        pdfContentByte.SetTextMatrix(0, 0);

                        pdfContentByte.ShowTextAligned(Element.ALIGN_CENTER, text,

                            locationX, locationY, opt.Rotation);


                        pdfContentByte.EndText();

                        break;

                }

            }


            pdfStamper.Close();

            pdfReader.Close();

            idx++;

            if (idx >= signOpts.Count) continue;

            //文件名重新赋值

            beforeFileName = afterFileName;

            afterFileName += "_sign";

        }


        return afterFileName + ".pdf";

    }


    //计算动态表达式的值

    public static T? Eval<T>(string expr, object context)

    {

        if (string.IsNullOrWhiteSpace(expr))

            return default;


        var target = new Interpreter();

        var input = JObject.FromObject(context);


        target.SetVariable("input", input.ToObject<ExpandoObject>());

        return target.Eval<T>(expr);

    }

}

  1. 测试调用

using Newtonsoft.Json;

using PdfSign;


//读取签名所需配置文件

var signOpts = await GetSignOpt();


if (signOpts != null && signOpts.Any())

{

    //执行 pdf 文件盖章

    var signFileName= SignService.PdfSign(signOpts, "test");

}


//读取配置文件

static async Task<List<SignOpt>?> GetSignOpt()

{

    var strSign = await File.ReadAllTextAsync("cfg.json");

    return JsonConvert.DeserializeObject<List<SignOpt>>(strSign);

}

  1. 效果展示
    原 pdf 文件如下图:

  2. 最终效果如下图:


作者:架构师小任
链接:https://juejin.cn/post/7377643248187080715
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



该文章在 2024/7/22 11:41:31 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved