简体   繁体   English

c#itextsharp PDF创建,每页带有水印

[英]c# itextsharp PDF creation with watermark on each page

I am trying to programmatically create a number of PDF documents with a watermark on each page using itextsharp (a C# port of Java's itext).我正在尝试使用 itextsharp(Java 的 itext 的 C# 端口)以编程方式创建许多带有水印的 PDF 文档。

I am able to do this after the document has been created using a PdfStamper.在使用 PdfStamper 创建文档后,我可以执行此操作。 However this seems to involve re-opening the document reading it and then creating a new document with the watermark on each page.然而,这似乎涉及重新打开文档阅读它,然后在每页上创建一个带有水印的新文档。

Is there a way of doing this during document creation?在文档创建期间有没有办法做到这一点?

After digging into it I found the best way was to add the watermark to each page as it was created.深入研究后,我发现最好的方法是在创建的每个页面上添加水印。 To do this I created a new class and implemented the IPdfPageEvent interface as follows:为此,我创建了一个新类并实现了 IPdfPageEvent 接口,如下所示:

    class PdfWriterEvents : IPdfPageEvent
    {
        string watermarkText = string.Empty;

        public PdfWriterEvents(string watermark) 
        {
            watermarkText = watermark;
        }

        public void OnOpenDocument(PdfWriter writer, Document document) { }
        public void OnCloseDocument(PdfWriter writer, Document document) { }
        public void OnStartPage(PdfWriter writer, Document document) {
            float fontSize = 80;
            float xPosition = 300;
            float yPosition = 400;
            float angle = 45;
            try
            {
                PdfContentByte under = writer.DirectContentUnder;
                BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
                under.BeginText();
                under.SetColorFill(BaseColor.LIGHT_GRAY);
                under.SetFontAndSize(baseFont, fontSize);
                under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
                under.EndText();
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
            }
        }
        public void OnEndPage(PdfWriter writer, Document document) { }
        public void OnParagraph(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnParagraphEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) { }
        public void OnChapterEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title) { }
        public void OnSectionEnd(PdfWriter writer, Document document, float paragraphPosition) { }
        public void OnGenericTag(PdfWriter writer, Document document, Rectangle rect, String text) { }

    }
}

This object is registered to handle the events as follows:这个对象被注册来处理如下事件:

PdfWriter docWriter = PdfWriter.GetInstance(document, new FileStream(outputLocation, FileMode.Create));
PdfWriterEvents writerEvent = new PdfWriterEvents(watermark);
docWriter.PageEvent = writerEvent;

Although Tim's solution seems very nice, I have managed to do the same thing (I believe) using the following code (perhaps iTextSharp was improved a bit since then...):虽然 Tim 的解决方案看起来很不错,但我已经设法使用以下代码(也许 iTextSharp 从那时起有所改进......)来做同样的事情(我相信):

    private byte[] AddWatermark(byte[] bytes, BaseFont bf)
    {
        using(var ms = new MemoryStream(10 * 1024))
        {
            using(var reader = new PdfReader(bytes))
            using(var stamper = new PdfStamper(reader, ms))
            {
                int times = reader.NumberOfPages;
                for (int i = 1; i <= times; i++)
                {
                    var dc = stamper.GetOverContent(i);
                    PdfHelper.AddWaterMark(dc, AppName, bf, 48, 35, new BaseColor(70, 70, 255), reader.GetPageSizeWithRotation(i));
                }
                stamper.Close();
            }
            return ms.ToArray();
        }
    }

    public static void AddWaterMark(PdfContentByte dc, string text, BaseFont font, float fontSize, float angle, BaseColor color, Rectangle realPageSize, Rectangle rect = null)
    {
        var gstate = new PdfGState { FillOpacity = 0.1f, StrokeOpacity = 0.3f };
        dc.SaveState();
        dc.SetGState(gstate);
        dc.SetColorFill(color);
        dc.BeginText();
        dc.SetFontAndSize(font, fontSize);
        var ps = rect ?? realPageSize; /*dc.PdfDocument.PageSize is not always correct*/
        var x = (ps.Right + ps.Left) / 2;
        var y = (ps.Bottom + ps.Top) / 2;
        dc.ShowTextAligned(Element.ALIGN_CENTER, text, x, y, angle);
        dc.EndText();
        dc.RestoreState();
    }

This will add a watermark on all pages of a PDF document that is provided as a byte array.这将在作为字节数组提供的 PDF 文档的所有页面上添加水印。

(You don't need to do it while creating the PDF.) (您无需在创建 PDF 时执行此操作。)

It seems working for both landscape and portrait and it probably works for documents with mixed orientations.它似乎适用于横向和纵向,并且可能适用于具有混合方向的文档。

Cheers!干杯! :) :)

string WatermarkLocation = "D:\\Images\\superseded.png";

Document document = new Document();
PdfReader pdfReader = new PdfReader(FileLocation);
PdfStamper stamp = new PdfStamper(pdfReader, new FileStream(FileLocation.Replace(".pdf", "[temp][file].pdf"), FileMode.Create));

iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(WatermarkLocation);
img.SetAbsolutePosition(125, 300); // set the position in the document where you want the watermark to appear (0,0 = bottom left corner of the page)

PdfContentByte waterMark;
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
    waterMark = stamp.GetOverContent(page);
    waterMark.AddImage(img);
}
stamp.FormFlattening = true;
stamp.Close();

// now delete the original file and rename the temp file to the original file
File.Delete(FileLocation);
File.Move(FileLocation.Replace(".pdf", "[temp][file].pdf"), FileLocation);

I used the first solution.我使用了第一种解决方案。 I was having trouble getting it to work at first.一开始我很难让它工作。 I getting green underlines under all of my public voids saying that it was going to hide some inherit member.我在我所有的公共空白下得到绿色下划线,说它会隐藏一些继承成员。

Basically I realized that I already had added a PagePageEventHelper and I basically just cut out the code for the OnStartPage.基本上我意识到我已经添加了一个 PagePageEventHelper 并且我基本上只是删除了 OnStartPage 的代码。 ALSO!还! For some reason I had to make all of my public void's public override void.出于某种原因,我不得不使我所有的公共无效的公共覆盖无效。

  public override void OnStartPage(PdfWriter writer, Document document)
        {
            if (condition)
            {
                string watermarkText = "-whatever you want your watermark to say-";
                float fontSize = 80;
                float xPosition = 300;
                float yPosition = 400;
                float angle = 45;
                try
                {
                    PdfContentByte under = writer.DirectContentUnder;
                    BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
                    under.BeginText();
                    under.SetColorFill(iTextSharp.text.pdf.CMYKColor.LIGHT_GRAY);
                    under.SetFontAndSize(baseFont, fontSize);
                    under.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, xPosition, yPosition, angle);
                    under.EndText();
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine(ex.Message);
                }
            }
        }

Yes, the Watermark class seems to be no more - odd.是的,Watermark 类似乎不再存在 - 奇怪。 However in the process of converting to iTextSharp 5.3, I found a simple way to add a watermark to a new document.但是在转换为 iTextSharp 5.3 的过程中,我发现了一个简单的方法来为新文档添加水印。

MemoryStream mem = new MemoryStream();

Document document = new Document();

PdfWriter writer = PdfWriter.GetInstance(document, mem);

PdfContentByte cb = writer.DirectContent;

document.Open();

document.NewPage();

Image watermark = Image.GetInstance(WATERMARK_URI);

watermark.SetAbsolutePosition(80, 200);

document.Add(watermark);

BaseFont bf = BaseFont.CreateFont(FONT, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);

cb.BeginText();

...

cb.EndText();

document.Close();

你不能在你做完之后在每一页上放水印吗?

In iTextSharp you should be able to programmatically add a watermark eg在 iTextSharp 中,您应该能够以编程方式添加水印,例如

Watermark watermark = new Watermark(Image.getInstance("watermark.jpg"), 200, 420);
document.Add(watermark);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM