word、pdf、excel及zip加密(含示例效果及工具类)

基于POI、zip4j 给word、pdf、excel及zip加密

需求说明:

许多人希望能够对自己的Office文件以及压缩的ZIP文件进行加密,以防止未经授权的访问和信息泄露。然而,使用WPS、Microsoft Office软件或其它压缩工具逐一对每一个文件进行加密,实在是耗时且费力,往往让人感到疲惫与沮丧。

因此,本文将详细介绍一种更为高效的解决方案,以免大家在人力和时间上面无谓的消耗。本文的主要内容结构包括以下几个部分:

1、所需依赖

2、文档类加密工具类 + 测试示例

3、zip包加密工具类 + 测试示例

效果如下:

1、所需依赖:

提前声明(JAR包版本已经经过筛选 尽量不用对依赖做变更,不然部分方法或者类不存在)且注意各个POI依赖之间的版本信息。

复制代码
  <!--其他包 与主题无关 为保完整性故完整列出 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>



    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.21</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.25</version>
        <scope>compile</scope>
    </dependency>


    <!-- office加密所需 -->

    <dependency>
        <groupId>org.apache.pdfbox</groupId>
        <artifactId>pdfbox</artifactId>
        <version>2.0.27</version>
    </dependency>

    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext7-core</artifactId>
        <version>7.1.11</version>
        <type>pom</type>
    </dependency>

    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
    </dependency>
    <!-- Apache POI -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>4.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.xmlbeans</groupId>
        <artifactId>xmlbeans</artifactId>
        <version>5.1.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-collections4</artifactId>
        <version>4.4</version>
    </dependency>

    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId>
        <version>1.0.6</version>
    </dependency>


    <!--ZIP包加密 所需  -->
    <dependency>
        <groupId>net.lingala.zip4j</groupId>
        <artifactId>zip4j</artifactId>
        <version>2.9.1</version>
    </dependency>

2、文档加密方法工具类:

java 复制代码
  package com.example.demo;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.crypt.standard.StandardEncryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.*;
import java.nio.file.Files;

/**
 * 类描述:文件加密工具类 (word、excel、pdf )
 * 如有新增 请补充到描述中。
 *
 * @author xú
 * @since 1.0.0  2024-08-27 04:45:19
 */
public class DocumentEncryptionUtil {

    private DocumentEncryptionUtil() {
    }

    /**
     * 方法描述:加密word文件
     *
     * @param file     文件
     * @param password 密码
     * @author xú
     * @since 1.0.0   2024-08-27 04:46:54
     */
    public static void encryptWordFile(File file, String password) {
        try (POIFSFileSystem fs = new POIFSFileSystem();
             FileInputStream fis = new FileInputStream(file);
             XWPFDocument document = new XWPFDocument(fis)) {
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
            Encryptor encryptor = info.getEncryptor();
            encryptor.confirmPassword(password);
            try (OutputStream os = encryptor.getDataStream(fs)) {
                document.write(os);
            }
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fs.writeFilesystem(fos);
            }
            //System.out.println("Encrypted Word file: " + file.getAbsolutePath());
        } catch (org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException e) {
            //System.out.println("已加密");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 方法描述:加密excel-xlsx
     *
     * @param file     文件
     * @param password 密码
     * @author xú 
     * @since 1.0.0   2024-08-27 05:10:51
     */
    public static void encryptExcelXlsx(File file, String password) {
        try (POIFSFileSystem fs = new POIFSFileSystem();
             FileInputStream fis = new FileInputStream(file);
             XSSFWorkbook workbook = new XSSFWorkbook(fis)) {
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
            Encryptor encryptor = info.getEncryptor();
            encryptor.confirmPassword(password);
            try (OutputStream os = encryptor.getDataStream(fs)) {
                workbook.write(os);
            }
            try (FileOutputStream fos = new FileOutputStream(file)) {
                fs.writeFilesystem(fos);
            }
            //System.out.println("Encrypted Excel file: " + file.getAbsolutePath());
        } catch (org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException e) {
            //System.out.println("已加密");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法描述:加密excel-xls
     *
     * @param file     文件
     * @param password 密码
     * @author xú 
     * @since 1.0.0   2024-08-27 05:10:45
     */
    public static void encryptExcelXls(File file, String password) {
        try (POIFSFileSystem fs = new POIFSFileSystem(); FileInputStream fis = new FileInputStream(file);
             HSSFWorkbook workbook = new HSSFWorkbook(fis)) {
            EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
            StandardEncryptor encryptor = (StandardEncryptor) info.getEncryptor();
            encryptor.confirmPassword(password);

            try (OutputStream os = encryptor.getDataStream(fs)) {
                workbook.write(os);
            }

            try (FileOutputStream fos = new FileOutputStream(file)) {
                fs.writeFilesystem(fos);
            }

            System.out.println("Encrypted Excel file: " + file.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 方法描述:加密pdf文件
     *
     * @param file     文件
     * @param password 密码
     * @author xú
     * @since 1.0.0   2024-08-27 04:46:05
     */
    public static void encryptPdfFile(File file, String password) {
        try (PDDocument document = PDDocument.load(file)) {
            // Set the encryption options
            StandardProtectionPolicy policy = new StandardProtectionPolicy(password, password, new org.apache.pdfbox.pdmodel.encryption.AccessPermission());
            policy.setEncryptionKeyLength(128); // You can set the key length to 128 or 256 bits
            document.protect(policy);
            document.save(file);
            //System.out.println("Encrypted PDF file: " + file.getAbsolutePath());
        } catch (org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException e) {
            //System.out.println("已加密");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试文档加密工具类

3、测试及测试结果展示:

java 复制代码
 public static void main(String[] args) {
        String directoryPath = "D:\\桌面\\项目文档"; // 替换为你本地的路径
        String backupDirectoryPath = "D:\\桌面\\备份"; // 替换为你的备份路径
        String password = "aaaaa111112DDD";  // 密码设置

        try {
            Files.createDirectories(Paths.get(backupDirectoryPath));

            Files.walkFileTree(Paths.get(directoryPath), new SimpleFileVisitor<>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String fileName = file.getFileName().toString().toLowerCase();

                    if (fileName.endsWith(".docx") || fileName.endsWith(".xlsx") || fileName.endsWith(".pdf")) {
                        Path backupFile = Paths.get(backupDirectoryPath, file.toString().substring(directoryPath.length()));
                        Files.createDirectories(backupFile.getParent());
                        Files.copy(file, backupFile, StandardCopyOption.REPLACE_EXISTING);
                        try {
                            if (fileName.endsWith(".docx")) {
                                encryptWordFile(file.toFile(), password);
                            } else if (fileName.endsWith(".xlsx")) {
                                encryptExcelFile(file.toFile(), password);
                            } else if (fileName.endsWith(".pdf")) {
                                encryptPdfFile(file.toFile(), password);
                            }
                        }catch (Exception ex){
                            ex.printStackTrace();
                        }
                        System.out.println("Processed file: " + file.toString());
                    } else {
                        System.out.println("Skipped file: " + file.toString());
                    }

                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    Path backupDir = Paths.get(backupDirectoryPath, dir.toString().substring(directoryPath.length()));
                    Files.createDirectories(backupDir);
                    System.out.println("Directory: " + dir.toString());
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4、 zip包加密工具类

java 复制代码
package com.example.demo;

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 类描述:zip包加密工具类
 *
 * @author xú chūn chéng
 * @version 1.0.0
 * @since 1.0.0  2024-08-27 04:49:55
 */
public class ZipEncryptionUtil {
    private ZipEncryptionUtil() {
    }

    /**
     * 方法描述:使用旧zip创建加密zip
     *
     * @param oldZipFile 需要加密的zip包文件
     * @param password   密码
     * @author xú
     * @since 1.0.0   2024-08-27 04:49:50
     */
    public static void createEncryptedZipWithOldZip(File oldZipFile, String password) {
        //创建新的加密zip文件
        String newZipFileName = oldZipFile.getParent() + File.separator + "encrypted_" + oldZipFile.getName();
        try (ZipFile newEncryptedZipFile = new ZipFile(newZipFileName, password.toCharArray())) {
            //设置加密的zip参数
            ZipParameters zipParameters = new ZipParameters();
            zipParameters.setCompressionMethod(CompressionMethod.DEFLATE);
            zipParameters.setCompressionLevel(CompressionLevel.NORMAL);
            zipParameters.setEncryptFiles(true);
            zipParameters.setEncryptionMethod(EncryptionMethod.AES);
            // 将旧的zip文件添加到新的加密zip文件中
            newEncryptedZipFile.addFile(oldZipFile, zipParameters);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //System.out.println("Created encrypted ZIP file: " + newZipFileName);
    }


    /**
     * 方法描述:加密zip文件 (会把OLD压缩文件解压开  然后重新打包加密) 慎用
     * ( 这种加密方式存在问题  当文件内部多层级的时候无法正常加密 且中文乱码)
     *
     * @param file     文件
     * @param password 密码
     * @author xú chūn chéng
     * @since 1.0.0   2024-08-27 04:48:46
     */
    public static void encryptZipFile(File file, String password) {
        try {
            File tempDir;
            try (ZipFile zipFile = new ZipFile(file, password.toCharArray())) {
                // 设置压缩文件
                ZipParameters zipParameters = new ZipParameters();
                zipParameters.setCompressionMethod(CompressionMethod.DEFLATE);
                zipParameters.setCompressionLevel(CompressionLevel.NORMAL);
                zipParameters.setEncryptFiles(true);
                zipParameters.setEncryptionMethod(EncryptionMethod.AES);

                //将所有文件解压缩到临时目录
                tempDir = Files.createTempDirectory("zip4j").toFile();
                zipFile.extractAll(tempDir.getAbsolutePath());

                // 从zip中删除所有文件
                List<FileHeader> fileHeaders = zipFile.getFileHeaders();
                List<FileHeader> headersToRemove = new ArrayList<>(fileHeaders); // 将要删除的文件头收集到一个新列表中

                for (FileHeader fileHeader : headersToRemove) {
                    zipFile.removeFile(fileHeader);
                }

                //使用加密重新打包文件
                for (File extractedFile : Objects.requireNonNull(tempDir.listFiles())) {
                    zipFile.addFile(extractedFile, zipParameters);
                }
            }

            //清理临时目录
            for (File extractedFile : Objects.requireNonNull(tempDir.listFiles())) {
                extractedFile.delete();
            }
            tempDir.delete();
            //System.out.println("Encrypted ZIP file: " + file.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5、ZIP 方式1测试:

java 复制代码
 public static void main(String[] args) {
        String directoryPath = "D:\\桌面\\新建文件夹\\已压缩_未归类"; // 替换为你本地的路径
        String backupDirectoryPath = "D:\\桌面\\备份"; // 替换为你的备份路径
        String password = "741841aaa333.";//密码 
        long maxSize = 1024L * 1024L * 1024L; // 1GB

        try {
            Files.createDirectories(Paths.get(backupDirectoryPath));

            // 首先收集所有要处理的文件
            List<Path> filesToProcess = new ArrayList<>();
            Files.walkFileTree(Paths.get(directoryPath), new SimpleFileVisitor<>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String fileName = file.getFileName().toString().toLowerCase();
                     //由于超过1G的文件处理时间过长 所需对此文件大小进行限制 最大为1GB
                    if (fileName.endsWith(".zip") && Files.size(file) <= maxSize) {
                        filesToProcess.add(file);
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    Path backupDir = Paths.get(backupDirectoryPath, dir.toString().substring(directoryPath.length()));
                    Files.createDirectories(backupDir);
                    return FileVisitResult.CONTINUE;
                }
            });

            // 然后处理收集到的文件
            int totalFiles = filesToProcess.size();
            for (int i = 0; i < totalFiles; i++) {
                Path file = filesToProcess.get(i);
                Path backupFile = Paths.get(backupDirectoryPath, file.toString().substring(directoryPath.length()));
                Files.createDirectories(backupFile.getParent());
                Files.copy(file, backupFile, StandardCopyOption.REPLACE_EXISTING);
                ZipEncryptionUtil.encryptZipFile(file.toFile(), password);
                // 记录进度
                System.out.printf("Processed file (%d/%d): %s%n", i + 1, totalFiles, file.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

6:zip2加密方式测试 :

需要创建一个新的 ZIP 文件,并将原有的 ZIP 文件(OLD 压缩文件)作为一个单独的文件放入新 ZIP 文件中,同时对新 ZIP 文件进行加密。

方法测试:

java 复制代码
  public static void main(String[] args) {
        String directoryPath = "D:\\桌面\\AAA"; // 替换为你本地的路径
        String backupDirectoryPath = "D:\\桌面\\备份"; // 替换为你的备份路径
        String password = "ssssssss.";
        long maxSize = 1024L * 1024L * 1024L; // 1GB

        try {
            Files.createDirectories(Paths.get(backupDirectoryPath));

            // 首先收集所有要处理的文件
            List<Path> filesToProcess = new ArrayList<>();
            Files.walkFileTree(Paths.get(directoryPath), new SimpleFileVisitor<>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                    String fileName = file.getFileName().toString().toLowerCase();
                    if (fileName.endsWith(".zip") && Files.size(file) <= maxSize) {
                        filesToProcess.add(file);
                    }
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                    Path backupDir = Paths.get(backupDirectoryPath, dir.toString().substring(directoryPath.length()));
                    Files.createDirectories(backupDir);
                    return FileVisitResult.CONTINUE;
                }
            });

            // 然后处理收集到的文件
            int totalFiles = filesToProcess.size();
            for (int i = 0; i < totalFiles; i++) {
                Path file = filesToProcess.get(i);
                Path backupFile = Paths.get(backupDirectoryPath, file.toString().substring(directoryPath.length()));
                Files.createDirectories(backupFile.getParent());
                Files.copy(file, backupFile, StandardCopyOption.REPLACE_EXISTING);

                ZipEncryptionUtil.createEncryptedZipWithOldZip(file.toFile(), password);

                // 记录进度
                System.out.printf("Processed file (%d/%d): %s%n", i + 1, totalFiles, file.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
相关推荐
李慕婉学姐1 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆3 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin3 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20053 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉4 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国4 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882484 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈5 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_995 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹5 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理