有时我们希望删除 PDF 文档的写保护/“加密”和数字签名,以便可以更改和重新签名文档。例如。因为原始文档丢失或被更改,并且数字签名已损坏(例如this文档)。
为此,我们使用了以下 iText 8 代码(事实上,展平 AcroForm 并不是最好的方法,例如因为交互式表单被禁用等):
public static byte[] cleanUpPdfItext(byte[] originalPdfData) throws Exception {
// Read the PDF document
try (
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PdfReader pdfReader = new PdfReader(new ByteArrayInputStream(originalPdfData)).setUnethicalReading(true);
PdfWriter pdfWriter = new PdfWriter(byteArrayOutputStream);
PdfDocument pdfDocument = new PdfDocument(pdfReader, pdfWriter)
) {
// Create the signature utils
SignatureUtil signatureUtil = new SignatureUtil(pdfDocument);
// Check if encrypted and/or contains signatures
boolean isEncrypted = pdfReader.isEncrypted();
boolean hasSignatures = !signatureUtil.getSignatureNames().isEmpty();
// Handle all cases
if (isEncrypted && hasSignatures) { // Encrypted and signatures
// Remove the signatures
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, true);
form.flattenFields();
// Write the changes to the output stream, so we can read them
pdfDocument.close();
// Get the manipulated document
return byteArrayOutputStream.toByteArray();
} else if (isEncrypted) { // Encrypted but no signatures
// Write the changes to the output stream, so we can read them
pdfDocument.close();
// Get the manipulated document
return byteArrayOutputStream.toByteArray();
} else { // Not encrypted/no signatures
// Return the original document data
return originalPdfData;
}
}
}
问题: 使用 pdfbox 执行此操作的等效代码是什么?删除写保护/“加密”并删除所有现有签名(尚未丢失),以便可以编辑和撤销文档?
我想出了这个初始版本:
public static byte[] cleanUpPdfbox(byte[] original) throws Exception {
try (
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
PDDocument pdDocument = Loader.loadPDF(original)
) {
// Check if encrypted or read only
AccessPermission accessPermission = pdDocument.getCurrentAccessPermission();
boolean isEncrypted = pdDocument.isEncrypted() || accessPermission.isReadOnly();
// Check if signatures exist
boolean hasSignatures = false;
PDAcroForm pdAcroForm = pdDocument.getDocumentCatalog().getAcroForm();
if (pdAcroForm != null) {
// Get a list of all signature fields
List<PDSignature> pdSignatures = pdDocument.getSignatureDictionaries();
hasSignatures = !pdSignatures.isEmpty();
}
// Remove all security if required
if (isEncrypted) {
pdDocument.setAllSecurityToBeRemoved(true);
}
// Remove all signatures
if (hasSignatures) {
// TODO: Code in question
}
// Write the document
pdDocument.save(byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
}
如果有修改,您可以在倒数第二个 %%EOF 之后中断。但是该文件不使用修订版。此解决方案从 fields 数组中删除签名字段(希望它位于顶层),并从页面上的注释数组中删除它。并从文档目录中删除 Perms 条目。
try (PDDocument doc = Loader.loadPDF(new File("Encrypted.pdf")))
{
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
List<PDField> oldFieldList = acroForm.getFields();
List<PDField> newFieldList = new ArrayList<>();
for (PDField field : oldFieldList)
{
if (!(field instanceof PDSignatureField))
{
newFieldList.add(field);
}
}
acroForm.setFields(newFieldList);
for (PDPage page : doc.getPages())
{
List<PDAnnotation> oldAnnotationList = page.getAnnotations();
List<PDAnnotation> newAnnotationList = new ArrayList<>();
for (PDAnnotation ann : oldAnnotationList)
{
if (ann instanceof PDAnnotationWidget && ann.getCOSObject().containsKey(COSName.V))
{
continue;
}
newAnnotationList.add(ann);
}
page.setAnnotations(newAnnotationList);
}
doc.setAllSecurityToBeRemoved(true);
doc.getDocumentCatalog().getCOSObject().removeItem(COSName.PERMS);
doc.save(new File("SO79055588-saved.pdf"));
}