OpenPDF的学习文档(第六章·PDF元数据和归档标准)

PDF元数据

  • 所谓的元数据Metadata,就是PDF文档的属性信息,不是打印在PDF页面上的。
  • addAuthor(String author) 添加作者,一般是创作人或组织。(张三,某某组织,某某办公室)
  • addCreator(String creator) 添加创建者,生成文档的上游系统或软件。(某某系统,Microsoft Word)
  • addProducer() 添加生产者,一般是底层渲染库。(OpenPDF, iText, PDF-XChange Editor)
  • addCreationDate(PdfDate date) 添加创建日期
  • addModificationDate(PdfDate date) 添加修改日期
  • addKeywords(String keywords) 添加关键字
  • addSubject(String subject) 添加主题
  • addTitle(String title) 添加标题
  • image
  • addHeader(String name, String content) 添加自定义的PDF元信息。
  • 严重警告:document.open();之前使用。
  • PdfWriter writer = PdfWriter.getInstance(document, outputStream);
    
    document.addAuthor("作者");
    document.addCreator("创建者");
    document.addProducer(); // 添加生产者
    
    document.addCreationDate(); // 创建日期
    document.addModificationDate(); // 修改日期
    
    document.addKeywords("关键字");
    document.addSubject("PDF主题"); // PDF主题
    document.addTitle("PDF标题"); // PDF标题
    
    
    document.open();
    document.add(new Paragraph("Hi"));
    document.close();
    

归档标准 PDF/A(Portable Document Format for Archival)

  • PDF归档:目的是确保文档在未来几十年甚至几百年后打开时,其外观、结构和可读性与最初创建时完全一致
  • ISO 标准组织(ISO 19005 系列) 主持创建标准。
  • 迄今为止,ISO组织一共发布了4代PDF/A标准
    • PDF/A-1(ISO 19005-1:2005,基于 PDF 1.4)

    • PDF/A-2(ISO 19005-2:2011,基于 PDF 1.7)

    • PDF/A-3(ISO 19005-3:2012,基于 PDF 1.7)

    • PDF/A-4(ISO 19005-4:2020,基于 PDF 2.0)

    • PDF/A-1PDF/A-3 中:有三个级别

      • -b:基本级,只保证视觉呈现一致。
      • -u:文本检索级,所有字符都有对应的 Unicode 映射,保证文本可以被正确复制和搜索。
      • -a:无障碍/结构化级,标签化 PDF(Tagged PDF)、标注文章逻辑顺序(如标题、段落、表格结构)、方便盲人阅读器等无障碍设备读取。
    • PDF/A-4 废弃了上述三个级别

      • PDF/A-4:基础模式
      • PDF/A-4f:允许嵌入非 PDF/A 的任意格式附件
      • PDF/A-4e:针对工程和 3D 图纸领域的归档
  • 在OpenPDF的PdfWriter类中,找到了一些关于PDF/A标准的常量。
  • /**
     * A PDF/X level.
     */
    public static final int PDFXNONE = 0;
    /**
     * A PDF/X level.
     */
    public static final int PDFX1A2001 = 1;
    
    // Open and Close methods + method that create the PDF
    /**
     * A PDF/X level.
     */
    public static final int PDFX32002 = 2;
    /**
     * PDFA-1A level.
     */
    public static final int PDFA1A = 3;
    /**
     * PDFA-1B level.
     */
    public static final int PDFA1B = 4;
    /**
     * PDFA-2A level.
     */
    public static final int PDFA2A = 5;
    /**
     * PDFA-2B level.
     */
    public static final int PDFA2B = 6;
    /**
     * PDFA-2U level.
     */
    public static final int PDFA2U = 7;
    /**
     * PDFA-3A level.
     */
    public static final int PDFA3A = 8;
    /**
     * PDFA-3B level.
     */
    public static final int PDFA3B = 9;
    /**
     * PDFA-3U level.
     */
    public static final int PDFA3U = 10;
    
  • 找到了一份官网示例,创建符合PDF/A-1b的PDF
  • public class PdfA1B {
    
        /**
         * Creates a document validating PDF/A-1b conformance
         *
         * @param args no arguments needed here
         */
        public static void main(String[] args) {
            System.out.println("PDF/A-1b");
    
            // step 1: creation of a document-object
            Document document = new Document();
    
            try {
    
                // step 2: create writer and set conformance
                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("PdfA1b.pdf"));
                // 关键点:设置PDFA1B属性。
                // 但是我没有搞明白PDF/A为什么要和PDF/X方法里校验
                writer.setPDFXConformance(PDFA1B);
    
                // step 3: open the document
                document.open();
    
                // create pdf dictionary with required entry
                PdfDictionary pdfDictionary = new PdfDictionary();
                pdfDictionary.put(PdfName.CREATIONDATE, writer.getInfo().get(PdfName.CREATIONDATE));
                pdfDictionary.put(PdfName.MODDATE, writer.getInfo().get(PdfName.MODDATE));
    
                try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
    
                    // embed dictionary in XmpWriter
                    XmpWriter xmpWriter = new XmpWriter(baos, pdfDictionary, PdfWriter.PDFA1B);
                    xmpWriter.close();
    
                    byte[] xmpMetadata = baos.toByteArray();
    
                    // set xmp metadata and output intents
                    writer.setXmpMetadata(xmpMetadata);
                    writer.setOutputIntents("Custom", "", null, "sRGB IEC61966-2.1",
                            ICC_Profile.getInstance(ColorSpace.CS_sRGB));
                }
    
                // step 4:
    
                // we make some content
                String fontDir = "org/openpdf/examples/fonts/";
    
                BaseFont notoBase = BaseFont.createFont(
                        Objects.requireNonNull(
                                PdfA1B.class.getClassLoader().getResource(fontDir + "noto/NotoSans-Regular.ttf")).getFile(),
                        BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                Font noto = new Font(notoBase, 10, Font.NORMAL);
    
                // a paragraph
                Paragraph p1 = new Paragraph("This document is compliant with PDF-A/1b requirements", noto);
    
                // some paragraph
                Paragraph p2 = new Paragraph("blah, blah, blah", noto);
    
                // we add the content
                document.add(p1);
                document.add(p2);
                document.add(p2);
                document.add(p2);
                document.add(p2);
                document.add(p2);
                document.add(p2);
                document.add(p2);
            } catch (DocumentException | IOException de) {
                System.err.println(de.getMessage());
            }
    
            // step 5: we close the document
            document.close();
        }
    }
    
  • 这里的例子有很大的问题,OpenPDF根本没有校验PDFA1B的逻辑。
  • 有兴趣的可以查看PdfXConformanceImp.checkPDFXConformance(PdfWriter writer, int key, Object obj1)PdfXConformance.setPDFXConformance(int pdfxConformance)源码。

PDF/X 印刷保证。

  • PDF/X-1a
  • PDF/X-3
  • PDF/X-4
  • PDF/X-6
  • OpenPDF只能保证PDF/X-1a:2001,还不一定全面。

这一部分知识尽量别用openPDF进行限制。

posted @ 2026-07-29 23:32  铁锅炖大鹅ing  阅读(16)  评论(0)    收藏  举报