介绍
最近工作上需要对word,excel,ppt,pdf等各类型文档密码检测,对文件进行分类,有密码的和没密码的做区分。查了一堆资料和GPT都不是很满意,最后东拼西凑搞了个相对全面的检测工具代码类,希望能给需要的人带来帮助。
说明
这段代码提供了一个全面的工具类,用于检测多种办公文档(.xls, .xlsx, .doc, .docx, .pdf, .ppt, .pptx)是否设置了密码保护。以下是该实现的核心逻辑和要点:
1、通用检测入口:通过isFileProtected(File file, String fileExtension)方法,根据文件扩展名调用特定的检测方法。
2、Excel文件检测(isExcelProtected(File file)): 使用WorkbookFactory.create()尝试打开文件,如果文件加密,会抛出EncryptedDocumentException异常。
3、Word文件检测(isWordProtected(File file)): 利用WordExtractor尝试读取文件内容,当文件加密时,会抛出EncryptedDocumentException异常,或者从异常信息中判断文件是否加密。
4、PDF文件检测(isPdfProtected(File file)): 使用PDFBox库的Loader.loadPDF()加载文件,然后检查PDDocument实例的isEncrypted()状态,或捕获InvalidPasswordException来判断是否加密。
5、PPT文件检测(isPptProtected(File file)): 对于.ppt文件使用HSLFSlideShow尝试读取,通过捕获异常并检查消息中是否包含“encrypted”关键字来判断文件是否加密。注意,对于.pptx文件,理论上应该使用与.xlsx类似的处理方式,但示例中未单独区分。
6、资源管理:使用try-with-resources语句确保文件输入流和各种文档对象在操作完成后能被正确关闭,同时利用自定义的IoUtil.close()方法进一步确保资源的释放(假设这是您项目中的一个辅助方法)。
7、日志记录:在捕获异常时记录错误日志,有助于追踪问题。
实现步骤
添加依赖
- poi-4.1.2
- hu-tool
- pdfbox
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.21</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.2</version>
</dependency>
工具类
public class TestFileEncrypt {
private static final Logger log = LoggerFactory.getLogger(TestFileEncrypt.class);
public static void main(String[] args) {
String filePath = "d:/tmp/enc/data0.xls"; // 替换为你要检查的文件路径
boolean isLikelyEncrypted = isExcelProtected(FileUtil.newFile(filePath));
System.out.println("文件是否加密的: " + isLikelyEncrypted);
}
// 创建通用方法,根据文件后缀名识别文件类型,调用不同的方法进行检测
public static boolean isFileProtected(File file, String fileExtension) {
switch (fileExtension.toLowerCase()) {
case "xls":
case "xlsx":
return isExcelProtected(file);
case "doc":
case "docx":
return isWordProtected(file);
case "pdf":
return isPdfProtected(file);
case "ppt":
case "pptx":
return isPptProtected(file);
default:
return false;
}
}
// 检查XLSX文件是否受密码保护
public static boolean isExcelProtected(File file) {
boolean isProtected = false;
Workbook sheets = null;
try (FileInputStream fis = new FileInputStream(file)) {
sheets = WorkbookFactory.create(fis);// 尝试打开XLSX文件
sheets.close();
} catch (EncryptedDocumentException e) {
isProtected = true; // 抛出异常表示文件受密码保护
} catch (IOException e) {
log.error("读取Excel文件失败:{},{}",file.getName(),e.getMessage());
} finally {
if (sheets != null) {
IoUtil.close(sheets);
}
return isProtected;
}
}
public static boolean isWordProtected(File file) {
boolean isProtected = false;
WordExtractor extractor = null;
try (FileInputStream fis = new FileInputStream(file)) {
// 创建WordExtractor以读取内容,这一步可能会在文件受保护时失败
extractor = new WordExtractor(fis);
extractor.close(); // 关闭提取器
} catch (EncryptedDocumentException e){
isProtected = true;
} catch (IOException e) {
if(e.getMessage().indexOf("EncryptedPackage") != -1){
isProtected = true;
}else{
log.error("读取Word文件失败:{},{}",file.getName(),e.getMessage());
}
} finally {
if(extractor!=null){
IoUtil.close(extractor);
}
return isProtected;
}
}
// 检查PDF文件是否受密码保护
public static boolean isPdfProtected(File file) {
boolean isEncrypted = false;
try (PDDocument document = Loader.loadPDF(file)) {
if (document.isEncrypted()) {
isEncrypted = true;
}
} catch (InvalidPasswordException e) {
isEncrypted = true;
} catch (IOException e) {
log.error("读取pdf文件失败:{},{}",file.getName(),e.getMessage());
}finally {
return isEncrypted;
}
}
public static boolean isPptProtected(File file) {
boolean isProtected = false;
HSLFSlideShow ppt=null;
try (FileInputStream fis = new FileInputStream(file)) {
ppt = new HSLFSlideShow(fis);
ppt.getPageSize();
ppt.close();
} catch (Exception e){
if(e.getMessage().toLowerCase().indexOf("encrypted")!=-1){
isProtected = true;
}
} finally {
if(ppt!=null){
IoUtil.close(ppt);
}
return isProtected;
}
}
}