如何在Java中检查PDF文件是否受密码保护?
我知道有几个工具/库可以做到这一点,但我想知道是否可能只用Java程序来实现。
try
{
document = PDDocument.load( yourPDFfile );
if( document.isEncrypted() )
{
//ITS ENCRYPTED!
}
}
正在使用Maven吗?
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0</version>
</dependency>
getNumberOfPages()
获取页面数量也是非常有帮助的。 - 0101100101更新
根据mkl在下面的评论中提到,似乎规范允许两种PDF结构: (1) 交叉引用表格 (2) 交叉引用流。以下解决方案仅针对第一种结构。需要更新此答案以解决第二种结构。
====
以上所有答案都涉及某些第三方库,而这正是OP已经知道的。OP正在寻求本机Java方法。我的答案是可以,但需要大量工作。
这将需要两个步骤:
步骤1: 确定PDF是否加密
根据Adobe的PDF 1.7规范(第97页和115页),如果尾部记录包含键“\Encrypted”,则PDF已加密(加密可能是简单的密码保护、RC4或AES或某些自定义加密)。以下是一个示例代码:
Boolean isEncrypted = Boolean.FALSE;
try {
byte[] byteArray = Files.readAllBytes(Paths.get("Resources/1.pdf"));
//Convert the binary bytes to String. Caution, it can result in loss of data. But for our purposes, we are simply interested in the String portion of the binary pdf data. So we should be fine.
String pdfContent = new String(byteArray);
int lastTrailerIndex = pdfContent.lastIndexOf("trailer");
if(lastTrailerIndex >= 0 && lastTrailerIndex < pdfContent.length()) {
String newString = pdfContent.substring(lastTrailerIndex, pdfContent.length());
int firstEOFIndex = newString.indexOf("%%EOF");
String trailer = newString.substring(0, firstEOFIndex);
if(trailer.contains("/Encrypt"))
isEncrypted = Boolean.TRUE;
}
}
catch(Exception e) {
System.out.println(e);
//Do nothing
}
步骤2: 确定加密类型
这一步比较复杂,暂时还没有代码示例。但以下是算法:
>forfiles /m *.pdf /C "cmd /c echo @file &pdfinfo @file|find /i \"Encrypted\""
"Certificate (9).pdf"
Encrypted: no
"ds872 source form.pdf"
Encrypted: AES 128-bit
"ds872 filled form.pdf"
Encrypted: AES 128-bit
"How to extract data from a particular area in a PDF file - Stack Overflow.pdf"
Encrypted: no
"Test.pdf"
Encrypted: no
>
使用 iText pdf API,我们可以识别受密码保护的 PDF。
示例:
try {
new PdfReader("C:\\Password_protected.pdf");
} catch (BadPasswordException e) {
System.out.println("PDF is password protected..");
} catch (Exception e) {
e.printStackTrace();
}
您可以使用Itext验证pdf,即可读写。
以下是代码片段:
boolean isValidPdf = false;
try {
InputStream tempStream = new FileInputStream(new File("path/to/pdffile.pdf"));
PdfReader reader = new PdfReader(tempStream);
isValidPdf = reader.isOpenedWithFullPermissions();
} catch (Exception e) {
isValidPdf = false;
}
if (isset($xref['trailer']['encrypt'])) {
echo('Your Allert message');
exit();}
3) 在您的 .php 表单提交页面(例如 upload.php)中插入以下内容:
for the first require '...yourdir.../vendor/autoload.php';
然后编写这个函数:
function pdftest_is_encrypted($form) {
$parser = new \Smalot\PdfParser\Parser();
$pdf = $parser->parseFile($form);
}
然后调用函数
pdftest_is_encrypted($_FILES["upfile"]["tmp_name"]);
这就是全部内容了,如果您尝试加载一个有密码的PDF文件,系统会返回一个错误信息“您的警告消息”。
java
编写的(而其他一些可能是用其他语言编写的,但这不是主题),对吧? :) 如果是这样,为什么不能编写自己的密码检查实现呢? - aga