如何使用PDFBox为PDF添加标记为ARTIFACT的可访问页码?
使用PDFBox添加标记为ARTIFACT的可访问页码
根据Tagged PDF最佳实践指南的3.7节Artifacts定义:
为显示进行内容排版与分页的过程会引入额外显示元素(如页码、表格边框),这类元素不属于ISO 32000-1定义的“真实内容”,被视为排版Artifacts(详见ISO 32000-1的14.8.2.2节“真实内容与Artifacts”)。带标签PDF要求明确区分真实内容与Artifacts。
以下是具体实现步骤:
1. 引入PDFBox依赖
如果使用Maven,在pom.xml中添加依赖(建议使用最新稳定版本):
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.32</version> </dependency>
2. 核心代码实现
通过遍历PDF页面,创建内容流添加页码,并将该内容标记为Artifact:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState; import org.apache.pdfbox.pdmodel.graphics.state.RenderingMode; import java.io.File; import java.io.IOException; public class ArtifactPageNumberAdder { public static void main(String[] args) { try (PDDocument doc = PDDocument.load(new File("input.pdf"))) { int totalPages = doc.getNumberOfPages(); for (int pageIdx = 0; pageIdx < totalPages; pageIdx++) { PDPage page = doc.getPage(pageIdx); PDRectangle mediaBox = page.getMediaBox(); float pageWidth = mediaBox.getWidth(); float pageHeight = mediaBox.getHeight(); float fontSize = 12; float bottomMargin = 20; // 以APPEND模式创建内容流,保留原页面内容 try (PDPageContentStream contentStream = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true)) { // 启动Artifact标记,声明此内容为非真实内容 contentStream.beginMarkedContent("Artifact", PDExtendedGraphicsState.getArtificialContentType()); // 设置文本样式 contentStream.setFont(org.apache.pdfbox.pdmodel.font.PDType1Font.HELVETICA, fontSize); contentStream.setRenderingMode(RenderingMode.FILL); contentStream.setNonStrokingColor(0, 0, 0); // 计算页码文本位置(底部居中) String pageText = String.format("%d/%d", pageIdx + 1, totalPages); float textWidth = org.apache.pdfbox.pdmodel.font.PDType1Font.HELVETICA.getStringWidth(pageText) / 1000 * fontSize; float textX = (pageWidth - textWidth) / 2; float textY = bottomMargin; // 绘制页码文本 contentStream.beginText(); contentStream.newLineAtOffset(textX, textY); contentStream.showText(pageText); contentStream.endText(); // 结束Artifact标记 contentStream.endMarkedContent(); } } doc.save("output_with_artifact_pages.pdf"); } catch (IOException e) { e.printStackTrace(); } } }
3. 关键细节说明
- Artifact标记逻辑:通过
beginMarkedContent和endMarkedContent包裹页码绘制代码,明确告诉PDF阅读器该内容属于排版Artifact,不属于核心内容。 - 内容流模式:使用
AppendMode.APPEND确保不会覆盖原页面已有内容,仅追加页码。 - 可访问性保障:即使标记为Artifact,仍需保证页码视觉位置合理,同时避免干扰屏幕阅读器对真实内容的解析。
内容的提问来源于stack exchange,提问作者DavesPlanet
相关产品推荐
相关产品推荐

