使用iText7给PDF顶部添加文本遇到的问题求助
iText7 在PDF顶部添加文本的问题解决
问题描述
用户尝试用iText7在PDF顶部添加文本,编写了如下C#函数:
private Stream AppendToDocumentAndReturnStream(string path, bool inline) { string text1 = "Date Range: 3/1/2023 - 3/31/2023"; string text2 = "Client: Client1, Client2, Client3,... this line may be long"; var stream = new MemoryStream(); var writer = new PdfWriter(stream); writer.SetCloseStream(false); var pdfDoc = new PdfDocument(new PdfReader(path), writer); var document = new Document(pdfDoc); var pageCount = pdfDoc.GetNumberOfPages(); for (var i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc.GetPage(i); Canvas canvas = new Canvas(page, page.GetPageSize()); // setting margin-botton to keep distance from original pdf content did NOT work var div = new Div().SetMargins(0, 10, 100, 10); if (inline) { div.Add(new Paragraph(text1).SetTextAlignment(TextAlignment.LEFT)); div.Add(new Div().SetKeepWithNext(true)); div.Add(new Paragraph(text2).SetTextAlignment(TextAlignment.RIGHT)); } else { div.Add(new Paragraph(text1).SetTextAlignment(TextAlignment.LEFT)); div.Add(new Paragraph(text2).SetTextAlignment(TextAlignment.LEFT)); } // tried to add this to keep an empty line between added text and original pdf content, but did NOT work too div.Add(new Paragraph(new Text("\n"))); canvas.Add(div); } document.Close(); stream.Position = 0; return stream; }
遇到两个问题:
- 当
inline为true时,需要text1左对齐、text2右对齐并显示在同一行,但text2跑到第二行; - 当
inline为false时,text1和text2分别左对齐显示两行,但text2距离原PDF内容过近,甚至会覆盖原内容,设置margin-bottom和换行符都无效。
问题1解决:同一行左右对齐
Paragraph是块级元素,每个实例会自动换行。要实现同一行左右对齐,可通过**制表位(TabStop)**实现:
- 创建单个
Paragraph,先添加text1; - 添加制表符
\t; - 设置右对齐的
TabStop,位置设为页面宽度减去左右边距; - 最后添加
text2。
修改后的inline分支代码:
if (inline) { Paragraph inlinePara = new Paragraph(); // 计算有效宽度:页面宽度减去左右各10px边距 float effectiveWidth = page.GetPageSize().GetWidth() - 20; // 添加右对齐制表位 inlinePara.AddTabStops(new TabStop(effectiveWidth, TabAlignment.RIGHT)); inlinePara.Add(text1).Add("\t").Add(text2); div.Add(inlinePara); }
问题2解决:避免覆盖原PDF内容
原代码中Canvas使用了整个页面尺寸,导致添加的文本从页面最顶部开始,和原内容重叠。解决思路是限制Canvas的绘制区域为页面顶部的一块独立区域:
- 获取页面的实际尺寸;
- 定义顶部区域的高度(根据文本行数调整,比如非inline场景设为80px);
- 创建仅覆盖顶部区域的
Rectangle,用它初始化Canvas; - 移除无效的换行符
Paragraph,通过顶部区域高度自然分隔新增文本和原内容。
修改后的循环内核心代码:
for (var i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc.GetPage(i); Rectangle pageSize = page.GetPageSize(); // 根据inline状态设置顶部区域高度 float topAreaHeight = inline ? 40 : 80; // 定义顶部绘制区域:左右留10px边距,顶部往下偏移对应高度 Rectangle topRect = new Rectangle( pageSize.GetLeft() + 10, pageSize.GetTop() - topAreaHeight, pageSize.GetWidth() - 20, topAreaHeight ); Canvas canvas = new Canvas(page, topRect); var div = new Div().SetMargins(0, 0, 10, 0); // 底部留10px间距 if (inline) { Paragraph inlinePara = new Paragraph(); float effectiveWidth = topRect.GetWidth(); inlinePara.AddTabStops(new TabStop(effectiveWidth, TabAlignment.RIGHT)); inlinePara.Add(text1).Add("\t").Add(text2); div.Add(inlinePara); } else { div.Add(new Paragraph(text1).SetTextAlignment(TextAlignment.LEFT)); div.Add(new Paragraph(text2).SetTextAlignment(TextAlignment.LEFT)); } canvas.Add(div); canvas.Close(); }
完整修改后的函数
private Stream AppendToDocumentAndReturnStream(string path, bool inline) { string text1 = "Date Range: 3/1/2023 - 3/31/2023"; string text2 = "Client: Client1, Client2, Client3,... this line may be long"; var stream = new MemoryStream(); var writer = new PdfWriter(stream); writer.SetCloseStream(false); var pdfDoc = new PdfDocument(new PdfReader(path), writer); var pageCount = pdfDoc.GetNumberOfPages(); float topAreaHeight = inline ? 40 : 80; for (var i = 1; i <= pageCount; i++) { PdfPage page = pdfDoc.GetPage(i); Rectangle pageSize = page.GetPageSize(); Rectangle topRect = new Rectangle( pageSize.GetLeft() + 10, pageSize.GetTop() - topAreaHeight, pageSize.GetWidth() - 20, topAreaHeight ); Canvas canvas = new Canvas(page, topRect); var div = new Div().SetMargins(0, 0, 10, 0); if (inline) { Paragraph inlinePara = new Paragraph(); float effectiveWidth = topRect.GetWidth(); inlinePara.AddTabStops(new TabStop(effectiveWidth, TabAlignment.RIGHT)); inlinePara.Add(text1).Add("\t").Add(text2); div.Add(inlinePara); } else { div.Add(new Paragraph(text1).SetTextAlignment(TextAlignment.LEFT)); div.Add(new Paragraph(text2).SetTextAlignment(TextAlignment.LEFT)); } canvas.Add(div); canvas.Close(); } pdfDoc.Close(); stream.Position = 0; return stream; }
关键修改说明
- 移除了无用的
Document实例(直接用Canvas操作页面,无需Document管理布局); - 针对
inline状态动态调整顶部区域高度,避免空间浪费; - 显式关闭
Canvas和PdfDocument,确保资源正确释放; - 通过限制Canvas绘制区域,彻底解决文本覆盖原内容的问题。
内容的提问来源于stack exchange,提问作者Hussein Dahir
相关产品推荐
相关产品推荐

