我正在尝试用Java生成PDF/A-1b,我尝试了很多不同的方法,但没有一个对我有用,我生成的每个PDF都无法通过PDF/A验证。 (我正在使用 VeraPDF 进行验证。)
到目前为止我的代码:
public byte[] convertirAPdfA(byte[] pdf) throws IOException, DocumentException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// Leer el documento PDF original
PdfReader reader = new PdfReader(pdf);
Document document = new Document(reader.getPageSizeWithRotation(1));
// Crear un PdfAWriter para escribir el nuevo PDF/A
PdfAWriter writer = PdfAWriter.getInstance(document, outputStream, PdfAConformanceLevel.PDF_A_1B);
// Abrir el documento para escribir
document.open();
// Crear y agregar XmpMetadata
writer.createXmpMetadata();
// Crear y embeder el perfil ICC
ICC_Profile icc = ICC_Profile.getInstance(getClass().getResourceAsStream("/icc/sRGB-IEC61966-2.1.icc"));
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
// Crear la fuente
BaseFont font = BaseFont.createFont("/fonts/BookAntiqua/BookAntiqua.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
writer.getDirectContent().setFontAndSize(font, 12);
// Añadir páginas del PDF original al nuevo PDF/A
PdfContentByte cb = writer.getDirectContent();
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
PdfImportedPage page = writer.getImportedPage(reader, i);
cb.addTemplate(page, 0, 0);
}
// Crear los metadatos XMP
XMPMeta xmpMeta = XMPMetaFactory.create();
try {
// Agregar metadatos DC (Dublin Core)
xmpMeta.setProperty(XMPConst.NS_DC, "dc:format", "application/pdf");
xmpMeta.setProperty(XMPConst.NS_DC, "dc:title", "Title of the Document");
xmpMeta.setProperty(XMPConst.NS_DC, "dc:creator", "Your Name");
xmpMeta.setProperty(XMPConst.NS_DC, "dc:description", "Description of the document");
// Agregar esquema de identificación PDF/A
XMPMetaFactory.getSchemaRegistry().registerNamespace("http://www.aiim.org/pdfa/ns/id/", "pdfaid");
xmpMeta.setProperty("http://www.aiim.org/pdfa/ns/id/", "pdfaid:part", "1");
xmpMeta.setProperty("http://www.aiim.org/pdfa/ns/id/", "pdfaid:conformance", "B");
// Serializar los metadatos XMP a un byte array
ByteArrayOutputStream xmpOutputStream = new ByteArrayOutputStream();
XMPMetaFactory.serialize(xmpMeta, xmpOutputStream, new SerializeOptions().setUseCompactFormat(true));
// Establecer los metadatos XMP en el documento
writer.setXmpMetadata(xmpOutputStream.toByteArray());
} catch (XMPException e) {
e.printStackTrace();
}
// Cerrar el documento y el lector
document.close();
reader.close();
// Retornar el PDF/A como byte[]
return outputStream.toByteArray();
}
我正在使用 Maven 项目并具有依赖项:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-pdfa</artifactId>
<version>5.5.13.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
</dependency>
目前,我正在使用通过验证的原始 PDF/A 功能测试代码,但正如我在开头所写的那样,结果不好。
验证器的错误:
MainXMPPackage
Identification_size == 1
root/document[0]/metadata[0](2 0 obj PDMetadata)/XMPPackage[0]
The document metadata stream doesn't contains PDF/A Identification Schema
经过一些测试,我有一个能够生成 PDF/A-1A 和 PDF/A-1B 的工作代码。它使用 pdf 字节数组作为参数和一致性级别的指示器。
我还发布了我用来检查现有 pdf 的一致性级别的代码
public byte[] transformAPdfA(byte[] documento, PdfAConformanceLevel nivelPdfA) throws IOException, DocumentException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PdfReader reader = new PdfReader(documento);
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfAConformanceLevel conformanceLevel = (nivelPdfA == PdfAConformanceLevel.PDF_A_1A) ?
PdfAConformanceLevel.PDF_A_1A : PdfAConformanceLevel.PDF_A_1B;
PdfAWriter writer = PdfAWriter.getInstance(document, outputStream, conformanceLevel);
if (nivelPdfA == PdfAConformanceLevel.PDF_A_1A) {
writer.setTagged();
}
document.open();
writer.createXmpMetadata();
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1",
ICC_Profile.getInstance(getClass().getResourceAsStream("/icc/sRGB-IEC61966-2.1.icc")));
writer.getDirectContent().setFontAndSize(BaseFont.createFont("/fonts/BookAntiqua/BookAntiqua.ttf",
BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 12);
document.close();
reader.close();
return outputStream.toByteArray();
}
public PdfAConformanceLevel obtainPdfaConformanceLevel(byte[] documento) throws AmapCsvPdfServiceException {
PdfReader reader;
byte[] metadataBytes = null;
try {
reader = new PdfReader(documento);
metadataBytes = reader.getMetadata();
reader.close();
if (metadataBytes != null) {
XMPMeta xmpMeta;
xmpMeta = XMPMetaFactory.parseFromBuffer(metadataBytes);
String pdfaPart = xmpMeta.getPropertyString("http://www.aiim.org/pdfa/ns/id/", "pdfaid:part");
String pdfaConformance = xmpMeta.getPropertyString("http://www.aiim.org/pdfa/ns/id/", "pdfaid:conformance");
if ("1".equals(pdfaPart)) {
if ("A".equalsIgnoreCase(pdfaConformance)) {
return PdfAConformanceLevel.PDF_A_1A; //PDF/A-1A
} else if ("B".equalsIgnoreCase(pdfaConformance)) {
return PdfAConformanceLevel.PDF_A_1B; //PDF/A-1B
}
}
}
} catch (XMPException | IOException e) {
throw new AmapCsvPdfServiceException("Error al obtener la informacion de Conformidad PDF/A", e);
}
return null; // No es un PDF/A o no se pudo determinar la conformidad
}