Pdf添加水印功能

背景

为防止涉密文件泄露,用户预览或下载pdf文件时,需要以用户信息作为水印内容加到pdf文件中。

实现

附件下载/预览接口:

/// <summary>
/// pdf附件下载接口
/// </summary>
/// <param name="fileId">fileId</param>
/// <param name="userId">用户id</param>
/// <returns></returns>
[HttpGet("{fileId}/{userId}")]
[AllowAnonymous]
public IActionResult DownloadPdfFile(string fileId,string userId)
{
    //从Mongo中下载文件
    FileByteInfo file = this._fileService.DownloadFileStream(fileId);
    if (file == null) return Ok("文件不存在或已被删除!");
    string type = "";
    System.IO.Stream fileStream = file.FileStream;	//文件流
    string fileName = file.FileName;
    if (!string.IsNullOrWhiteSpace(userId))
    {
        //获取用户身份
        User user = this._userService.GetUser(userId);
        if (user != null)
        {
            //水印:姓名(登录名 所属部门)
            string waterMarkText = $"{user.Name}({user.Code}) {user.ParentName}";
            System.IO.Stream waterPdfStream = PDFHelper.AddWatermark(fileStream, waterMarkText);
            //pdf添加水印
            if (waterPdfStream != null)
            {
                fileStream = waterPdfStream;
            }
        }
    }
    System.IO.Stream fbyte = fileStream;
    try
    {
        var provider = new FileExtensionContentTypeProvider();
        type = provider.Mappings[file.ContentType];
    }
    catch (KeyNotFoundException)
    {
        type = "application/x-msdownload";
    }
    return File(fbyte, type, fileName);
}

● 根据file获取文件流,调用AddWatermark将流添加水印

PDFHelper类:
若出现本地调试支持,部署到docker后预览出错,可能是服务器字体问题:
//本地调用这个配置
BaseFont font = BaseFont.CreateFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
//docker下用这个配置
BaseFont font = BaseFont.CreateFont("/usr/share/fonts/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

 public static class PDFHelper
 {
     /// <summary>
     /// 添加倾斜水印
     /// </summary>
     /// <param name="pdfStream">pdf文件流</param>
     /// <param name="waterMarkName">水印字符串</param>
     /// <param name="width">页面宽度</param>
     /// <param name="height">页面高度</param>
     public static MemoryStream AddWatermark(Stream pdfStream, string waterMarkName)
     {
         PdfReader pdfReader = null;
         PdfStamper pdfStamper = null;

         MemoryStream outStream = new MemoryStream();
         try
         {
             pdfStream.Position = 0;
             pdfReader = new PdfReader(pdfStream);
             pdfStamper = new PdfStamper(pdfReader, outStream);
             int total = pdfReader.NumberOfPages + 1;
             iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
             float width = psize.Width;
             float height = psize.Height;
             PdfContentByte content;
             //本地调用这个配置
             //BaseFont font = BaseFont.CreateFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);   
             //docker下用这个配置
             BaseFont font = BaseFont.CreateFont("/usr/share/fonts/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);    

             PdfGState gs = new PdfGState();
             int fontSize = 28;
             for (int i = 1; i < total; i++)
             {
                 //在内容上方加水印 ;content = pdfStamper.GetUnderContent(i);//在内容下方加水印
                 content = pdfStamper.GetOverContent(i);

                 gs.FillOpacity = 0.5f;   //透明度
                 content.SetGState(gs);
                 content.SetGrayFill(0.5f);
                 //开始写入文本
                 content.BeginText();
                 content.SetColorFill(BaseColor.Blue);
                 content.SetFontAndSize(font, fontSize);
                 content.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2 + 150, height / 2 + 150, 55);
                 content.SetColorFill(BaseColor.Blue);
                 content.SetFontAndSize(font, fontSize);
                 content.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2 - 150, height / 2 - 150, 55);
                 content.EndText();
             }
         }
         catch (Exception ex)
         {
             Console.WriteLine($"AddWatermark error:{ex.Message}, innerException:{ex.InnerException?.Message},stack:{ex.StackTrace}");
             outStream = null;
         }
         finally
         {
             if (pdfStamper != null)
                 pdfStamper.Close();
             if (pdfReader != null)
                 pdfReader.Close();
             if (outStream != null)
                 outStream.Position = 0; //必须重置位置,再写MongoDB
         }
         return outStream;
     }
     
     /// <summary>
     /// 加图片水印
     /// </summary>
     /// <param name="inputfilepath">源文件路径</param>
     /// <param name="outputfilepath">输出路径</param>
     /// <param name="modelPicName">图片地址</param>
     /// <param name="top">图片水印top</param>
     /// <param name="left">图片水印left</param>
     /// <returns></returns>
     public static bool AddImageWatermarkPDF(string inputfilepath, string outputfilepath, string modelPicName, float top, float left)
     {
         PdfReader pdfReader = null;
         PdfStamper pdfStamper = null;
         try
         {
             pdfReader = new PdfReader(inputfilepath);
             int numberOfPages = pdfReader.NumberOfPages;
             iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
             float width = psize.Width;
             float height = psize.Height;
             pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create));
             PdfContentByte waterMarkContent;
             iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(modelPicName);
             image.GrayFill = 20;//透明度,灰色填充
             //image.Rotation //旋转
             //image.RotationDegrees //旋转角度
             //水印的位置
             if (left < 0)
             {
                 left = width / 2 - image.Width + left;
             }

             //image.SetAbsolutePosition(left, (height - image.Height) - top);
             image.SetAbsolutePosition(left, (height / 2 - image.Height) - top);
             //每一页加水印,也可以设置某一页加水印
             for (int i = 1; i <= numberOfPages; i++)
             {
                 //waterMarkContent = pdfStamper.GetUnderContent(i);//内容下层加水印
                 waterMarkContent = pdfStamper.GetOverContent(i);//内容上层加水印

                 waterMarkContent.AddImage(image);
             }
             return true;
         }
         catch (Exception ex)
         {
             throw ex;
         }
         finally
         {
             if (pdfStamper != null)
                 pdfStamper.Close();

             if (pdfReader != null)
                 pdfReader.Close();
         }
     }
     /// <summary>
     /// 添加普通偏转角度文字水印 
     /// </summary>
     /// <param name="inputfilepath">源文件路径</param>
     /// <param name="outputfilepath">输出路径</param>
     /// <param name="waterMarkName">水印内容</param>
     public static void AddWordWatermark2PDF(string inputfilepath, string outputfilepath, string waterMarkName)
     {
         //PDFHelper.AddWordWatermark2PDF("F:\\pdf1.pdf", "F:\\pdf1副本.pdf", "我是水印内容");
         PdfReader pdfReader = null;
         PdfStamper pdfStamper = null;
         try
         {
             pdfReader = new PdfReader(inputfilepath);
             pdfStamper = new PdfStamper(pdfReader, new FileStream(outputfilepath, FileMode.Create));
             int total = pdfReader.NumberOfPages + 1;
             iTextSharp.text.Rectangle psize = pdfReader.GetPageSize(1);
             float width = psize.Width;
             float height = psize.Height;
             PdfContentByte content;
             BaseFont font = BaseFont.CreateFont(@"C:\WINDOWS\Fonts\SIMFANG.TTF", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
             PdfGState gs = new PdfGState();
             for (int i = 1; i < total; i++)
             {
                 //在内容上方加水印
                 content = pdfStamper.GetUnderContent(i);
                 //content = pdfStamper.GetUnderContent(i);//在内容下方加水印
                 //透明度
                 gs.FillOpacity = 0.5f;
                 content.SetGState(gs);
                 content.SetGrayFill(0.5f);
                 //开始写入文本
                 content.BeginText();
                 //content.SetColorFill(BaseColor.LIGHT_GRAY);
                 //content.SetFontAndSize(font, 100);
                 //content.SetTextMatrix(0, 0);
                 //content.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2 - 50, height / 2 - 50, 55);
                 content.SetColorFill(BaseColor.Gray);
                 content.SetFontAndSize(font, 16);
                 content.ShowTextAligned(Element.ALIGN_CENTER, waterMarkName, width / 2 - 50, height / 2 - 50, 55);
                 content.EndText();
             }
         }
         catch (Exception ex)
         {
             throw ex;
         }
         finally
         {
             if (pdfStamper != null)
                 pdfStamper.Close();

             if (pdfReader != null)
                 pdfReader.Close();
         }
     }
 }


效果图

posted @ 2022-06-16 17:00  齐大齐  阅读(580)  评论(0编辑  收藏  举报