如何正确加密合并的pdf文档
How to encrypt a merged pdfdocument properly
我的 pdfBox API 有问题。我正在尝试使用以下代码加密合并的 pdfdocument:
这是合并/创建文档的函数
public static void fillMultipleReportsInOne(List<report> reports) throws IOException {
PDFMergerUtility PDFmerger = new PDFMergerUtility();
PDDocument resultPDF = new PDDocument();
for (report report : reports) {
try
{
PDDocument pdfDocument = PDDocument.load(new File(SRC + "test.pdf"));
// get the document catalog
PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
// as there might not be an AcroForm entry a null check is necessary
setFormFields(acroForm, report.getName(), report.getArea(), report.getOperatingActivities(), report.getVocationlaSchool(), report.getWeeklyTopics());
// Save and close the filled out form.
PDFmerger.appendDocument(resultPDF, pdfDocument);
} catch (Exception e) {
e.printStackTrace();
}
}
encryptPDF(resultPDF, SRC + "merged.pdf");
}
这是加密函数:
public static PDDocument encryptPDF(PDDocument pddocumentToEncrypt, String SRC) {
// Define the length of the encryption key.
// Possible values are 40 or 128 (256 will be available in PDFBox 2.0).
int keyLength = 128;
AccessPermission ap = new AccessPermission();
// Disable printing, everything else is allowed
ap.setCanModifyAnnotations(false);
ap.setCanFillInForm(false);
ap.setCanModify(false);
// Owner password (to open the file with all permissions) is "12345"
// User password (to open the file but with restricted permissions, is empty here)
StandardProtectionPolicy spp = new StandardProtectionPolicy("12334", "", ap);
spp.setEncryptionKeyLength(keyLength);
spp.setPermissions(ap);
try {
pddocumentToEncrypt.protect(spp);
pddocumentToEncrypt.save(SRC);
pddocumentToEncrypt.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return pddocumentToEncrypt;
}
最后用所有样本数据调用函数
report report1 = new report("TestUser1", "P&T", "operatingActivities", "weeklyTopics","vocationalSchool");
report report2 = new report("TestUser2", "P&T2", "operatingActivities2", "weeklyTopics2","vocationalSchool2");
report report3 = new report("TestUser3", "P&T3", "operatingActivities3", "weeklyTopics3","vocationalSchool3");
report report4 = new report("TestUser4", "P&T4", "operatingActivities4", "weeklyTopics4","vocationalSchool4");
List<report> reports = new ArrayList<>();
reports.add(report1);
reports.add(report2);
reports.add(report3);
reports.add(report4);
fillMultipleReportsInOne(reports);
我的结果是这样的:
结果
只有第一个字段填充了数据,而所有字段都应该有
这绝对是一个加密问题,因为当我删除 document.protect() 行时,数据已正确填充。我还尝试了 acroForm.flatten() 函数 -> 没有成功...
也许有人有同样的问题并且愿意提供帮助:)
提前致谢
- 亚历克斯
这是粘贴到 pastebin 中的整个文件:
https://pastebin.com/L9auaTGH
用代码行
pddocumentToEncrypt.getDocumentCatalog().getAcroForm().refreshAppearances();
在我的加密函数中,它起作用了
通话中
pddocumentToEncrypt.getDocumentCatalog().getAcroForm().refreshAppearances();
在 2.0 版本中修复了这个问题。当设置 /NeedAppearances 时,该版本不会在 setValue()
调用中设置外观(即表单值的视觉表示)(参见 PDTerminalField.applyChange()
)。 /NeedAppearances 设置(当为真时)意味着查看应用程序应该创建外观,以便中间的处理应用程序不需要这样做;我怀疑一个或多个权限设置阻止 Adobe Reader 在显示时更改它。
另一个解决方案是调用
pdfDocument.getDocumentCatalog().getAcroForm().setNeedAppearances(false);
在设置表单值之前。
唯一未解之谜是为什么第一个值在合并文件中可见。
我的 pdfBox API 有问题。我正在尝试使用以下代码加密合并的 pdfdocument:
这是合并/创建文档的函数
public static void fillMultipleReportsInOne(List<report> reports) throws IOException {
PDFMergerUtility PDFmerger = new PDFMergerUtility();
PDDocument resultPDF = new PDDocument();
for (report report : reports) {
try
{
PDDocument pdfDocument = PDDocument.load(new File(SRC + "test.pdf"));
// get the document catalog
PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
// as there might not be an AcroForm entry a null check is necessary
setFormFields(acroForm, report.getName(), report.getArea(), report.getOperatingActivities(), report.getVocationlaSchool(), report.getWeeklyTopics());
// Save and close the filled out form.
PDFmerger.appendDocument(resultPDF, pdfDocument);
} catch (Exception e) {
e.printStackTrace();
}
}
encryptPDF(resultPDF, SRC + "merged.pdf");
}
这是加密函数:
public static PDDocument encryptPDF(PDDocument pddocumentToEncrypt, String SRC) {
// Define the length of the encryption key.
// Possible values are 40 or 128 (256 will be available in PDFBox 2.0).
int keyLength = 128;
AccessPermission ap = new AccessPermission();
// Disable printing, everything else is allowed
ap.setCanModifyAnnotations(false);
ap.setCanFillInForm(false);
ap.setCanModify(false);
// Owner password (to open the file with all permissions) is "12345"
// User password (to open the file but with restricted permissions, is empty here)
StandardProtectionPolicy spp = new StandardProtectionPolicy("12334", "", ap);
spp.setEncryptionKeyLength(keyLength);
spp.setPermissions(ap);
try {
pddocumentToEncrypt.protect(spp);
pddocumentToEncrypt.save(SRC);
pddocumentToEncrypt.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return pddocumentToEncrypt;
}
最后用所有样本数据调用函数
report report1 = new report("TestUser1", "P&T", "operatingActivities", "weeklyTopics","vocationalSchool");
report report2 = new report("TestUser2", "P&T2", "operatingActivities2", "weeklyTopics2","vocationalSchool2");
report report3 = new report("TestUser3", "P&T3", "operatingActivities3", "weeklyTopics3","vocationalSchool3");
report report4 = new report("TestUser4", "P&T4", "operatingActivities4", "weeklyTopics4","vocationalSchool4");
List<report> reports = new ArrayList<>();
reports.add(report1);
reports.add(report2);
reports.add(report3);
reports.add(report4);
fillMultipleReportsInOne(reports);
我的结果是这样的:
结果
只有第一个字段填充了数据,而所有字段都应该有 这绝对是一个加密问题,因为当我删除 document.protect() 行时,数据已正确填充。我还尝试了 acroForm.flatten() 函数 -> 没有成功...
也许有人有同样的问题并且愿意提供帮助:) 提前致谢 - 亚历克斯
这是粘贴到 pastebin 中的整个文件: https://pastebin.com/L9auaTGH
用代码行
pddocumentToEncrypt.getDocumentCatalog().getAcroForm().refreshAppearances();
在我的加密函数中,它起作用了
通话中
pddocumentToEncrypt.getDocumentCatalog().getAcroForm().refreshAppearances();
在 2.0 版本中修复了这个问题。当设置 /NeedAppearances 时,该版本不会在 setValue()
调用中设置外观(即表单值的视觉表示)(参见 PDTerminalField.applyChange()
)。 /NeedAppearances 设置(当为真时)意味着查看应用程序应该创建外观,以便中间的处理应用程序不需要这样做;我怀疑一个或多个权限设置阻止 Adobe Reader 在显示时更改它。
另一个解决方案是调用
pdfDocument.getDocumentCatalog().getAcroForm().setNeedAppearances(false);
在设置表单值之前。
唯一未解之谜是为什么第一个值在合并文件中可见。