介紹
最近工作上需要對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;}}}