Java利用poi实现word,excel,ppt,pdf等各类型文档密码检测

介绍

最近工作上需要对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
xml 复制代码
<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>

工具类

java 复制代码
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;
        }
    }

}
相关推荐
前行的小黑炭33 分钟前
设计模式:为什么使用模板设计模式(不相同的步骤进行抽取,使用不同的子类实现)减少重复代码,让代码更好维护。
android·java·kotlin
Java技术小馆38 分钟前
如何设计一个本地缓存
java·面试·架构
XuanXu1 小时前
Java AQS原理以及应用
java
风象南4 小时前
SpringBoot中6种自定义starter开发方法
java·spring boot·后端
mghio13 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室18 小时前
java日常开发笔记和开发问题记录
java
咖啡教室18 小时前
java练习项目记录笔记
java
鱼樱前端19 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea19 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq