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();
        }
    }
相关推荐
阿伟*rui6 分钟前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端
aloha_7895 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
hairenjing11235 小时前
使用 Mac 数据恢复从 iPhoto 图库中恢复照片
windows·stm32·嵌入式硬件·macos·word
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet