c# itextsharp PDF 创建每个页面上都有水印
Posted
技术标签:
【中文标题】c# itextsharp PDF 创建每个页面上都有水印【英文标题】:c# itextsharp PDF creation with watermark on each page 【发布时间】:2011-01-23 05:50:17 【问题描述】:我正在尝试使用 itextsharp(Java 的 itext 的 C# 端口)以编程方式在每个页面上创建许多带有水印的 PDF 文档。
我可以在使用 PdfStamper 创建文档后执行此操作。然而,这似乎涉及重新打开阅读它的文档,然后在每页上创建一个带有水印的新文档。
在文档创建期间有没有办法做到这一点?
【问题讨论】:
【参考方案1】:在深入研究之后,我发现最好的方法是在每个页面创建时添加水印。为此,我创建了一个新类并实现了 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)
这个对象被注册来处理如下事件:
PdfWriter docWriter = PdfWriter.GetInstance(document, new FileStream(outputLocation, FileMode.Create));
PdfWriterEvents writerEvent = new PdfWriterEvents(watermark);
docWriter.PageEvent = writerEvent;
【讨论】:
抱歉,我在创建的 PDF 上没有水印。你能告诉我,是什么问题。我已经使用了上面提供的确切代码。 横向页面呢?我试过 page.Width/2 和 page.Height/2 但横向页面被视为普通页面 - >对齐的文本不在页面中心。 使用 RazorPDF,缺少 BaseColor.LIGHT_GRAY。在这种情况下,请转至under.SetColorFill(iTextSharp.text.pdf.CMYKColor.LIGHT_GRAY);
我得到这个错误:他的名字“水印”在当前上下文中不存在。我该如何纠正它?目前,我正在使用两个类,其中一个包含 pdf 的生成和你的类......我如何让两个类相互交谈,以便它知道水印是什么?
如何在首页添加水印?我有一个 3 页的文档,它只出现在第 2 页和第 3 页。非常感谢您的回复:)【参考方案2】:
虽然 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();
这将在以字节数组形式提供的 PDF 文档的所有页面上添加水印。
(您在创建 PDF 时不需要这样做。)
它似乎适用于横向和纵向,它可能适用于具有混合方向的文档。
干杯! :)
【讨论】:
如果您的用例是创建新的 PDF 并添加水印,您可能更喜欢 Tim 提出的一次性变体,因为它使用的资源更少。如果您的用例是获取现有的 PDF 并为其添加水印,那么您的解决方案是合适的。 谢谢。这个解决方案对我很有用。我有一个基于此代码的示例 ASP.NET 核心项目。如果有人有兴趣,请在我的github 此解决方案有效,谢谢,但我使用电子邮件地址作为水印,显然它是可点击的。当我单击它时,它会打开 Outlook 应用程序。关于如何阻止它的任何想法?谢谢。 @MariusPopa 不确定这是否可行,这有点小技巧,但也许您可以在电子邮件地址中插入一些软连字符 (Unicode U+00AD)(例如,在 at 符号之前) 这将是不可见的,但它会使电子邮件检测器认为它不是电子邮件。我没有尝试过,但它可能有效。很可能有更好的方法来做到这一点,但我还没有真正尝试过。 @NoOne 如何为长字符串设置多行?【参考方案3】: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);
【讨论】:
【参考方案4】:我使用了第一个解决方案。一开始我很难让它工作。我在所有公共空白下都得到了绿色下划线,表示它将隐藏一些继承成员。
基本上我意识到我已经添加了一个 PagePageEventHelper,我基本上只是剪掉了 OnStartPage 的代码。还!出于某种原因,我不得不将我所有的公共无效的公共覆盖无效。
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);
【讨论】:
【参考方案5】:你不能在制作完之后在每一页上打上水印吗?
【讨论】:
【参考方案6】:是的,Watermark 类似乎不再是 - 奇怪了。但是在转换到 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();
【讨论】:
【参考方案7】:在 iTextSharp 中,您应该能够以编程方式添加水印,例如
Watermark watermark = new Watermark(Image.getInstance("watermark.jpg"), 200, 420);
document.Add(watermark);
【讨论】:
是的,我想过;在线查找有很多包含 Watermark 类的示例代码 - 但我相信这已从库中删除:( 如果他们删除了它,我会感到震惊。也许他们刚刚更改了其名称空间?您是否尝试过使用反射器查看组件?以上是关于c# itextsharp PDF 创建每个页面上都有水印的主要内容,如果未能解决你的问题,请参考以下文章