文件批量添加水印和密码合并单元格完整版

这段代码是一个 Java 方法,用于向文件添加水印和密码。您解释一下:

首先,它接受一个 fileAddress 参数,表示文件的地址。

然后,它创建了一个线程安全的列表 fileDatas,用于存储文件数据。

接下来,它尝试读取文件流,并获取所有 sheet 的数据。

在循环中,它逐个读取每个 sheet 的数据,并将其添加到 fileDatas 列表中。

如果在读取数据时发生异常,它会记录错误并抛出运行时异常。

最后,它生成一个新的文件名 newFileName,并使用 generationFileAddress 方法生成带有水印和密码的文件地址。

请注意,代码中的一些变量(例如 fileUrl、dto)在这里没有定义,您需要根据您的实际情况进行替换。如果您有其他问题或需要更详细的解释,请随时告知!😊

java 复制代码
	/**
	*文件添加水印密码
	*/
 public String fileAddWatermarkPassword(String fileAddress) {
        final String fileUrl;
        try {
            fileUrl = AESUtils.decrypt(fileAddress);
        } catch (Exception e) {
            LogUtil.error("报表数据提取", String.format("无法解密文件地址:%s", dto.getFileAddress()), null, e);
            throw new RuntimeException("无法解密文件地址", e);
        }

        List<List<List<String>>> fileDatas = new ArrayList<>();
        Map<Integer, List<CellRangeAddress>> sheetMergedRegions = new HashMap<>();


        try (InputStream inputStream = readFileStream(fileUrl);
             Workbook workbook = WorkbookFactory.create(inputStream)) {
            FormulaEvaluator formulaEvaluator = workbook.getCreationHelper().createFormulaEvaluator();

            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                Sheet sheet = workbook.getSheetAt(i);
                List<List<String>> fileData = processSheet(sheet,  formulaEvaluator);
                fileDatas.add(fileData);

                //捕捉合并区域
                sheetMergedRegions.put(i, new ArrayList<>(sheet.getMergedRegions()));
            }
        } catch (IOException | InvalidFormatException e) {
            LogUtil.error("报表数据提取", String.format("无法读取文件流, 文件地址:%s", fileUrl), null, e);
            throw new RuntimeException("无法读取文件流", e);
        }

        String newFileName = dto.getDownloadDataType() + ".xlsx";
        String fileAddress = generationFileAddress(fileDatas, sheetMergedRegions, newFileName, dto.getUseId(), dto.getUseName());

        return fileAddress;
    }
java 复制代码
	/**
	* 处理合并单元格为空处理
	*/
    private List<List<String>> processSheet(Sheet sheet, FormulaEvaluator formulaEvaluator) {
        List<List<String>> fileData = new ArrayList<>();

        for (Row row : sheet) {
            List<String> rowData = new ArrayList<>();
            // Initialize row with empty strings for missing cells
            int lastCellNum = row.getLastCellNum();
            for (int i = 0; i < lastCellNum; i++) {
                rowData.add(""); // Default to empty string for all cells
            }

            for (Cell cell : row) {
                int cellIndex = cell.getColumnIndex();
                String cellValue = getCellValue(cell, formulaEvaluator);
                rowData.set(cellIndex, cellValue); // Set cell value, handles empty cells
            }

            fileData.add(rowData);
        }
        return fileData;
    }
java 复制代码
	/**
	* 计算每个单元格的值
	*/
	     private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#");
    public static String getCellValue(Cell cell, FormulaEvaluator formulaEvaluator) {
   
        if (cell == null) {
            return "";
        }

        switch (cell.getCellType()) {
            case 1:
                return cell.getStringCellValue();
            case 0:
                if (DateUtil.isCellDateFormatted(cell)) {
                    // Format as date if needed
                    return cell.getDateCellValue().toString();
                } else {
                    // Format numeric value
                    return DECIMAL_FORMAT.format(cell.getNumericCellValue());
                }
            case 4:
                return Boolean.toString(cell.getBooleanCellValue());
            case 2:
                // Evaluate formula
                return getCellValue(formulaEvaluator.evaluateInCell(cell), formulaEvaluator);
            default:
                return "";
        }
    }
java 复制代码
    /**
     * 生成文件地址
     * @param data  数据内容
     * @param fileName  文件名
     * @param useId 操作者
     * @return
     */
  public String generationFileAddress(List<List<List<String>>> data, Map<Integer, List<CellRangeAddress>> sheetMergedRegions, String fileName, String useId, String useName) {
        String randomName = UUID.randomUUID() + "_" + fileName;
        String fileAddress;
        File tempFile = null;

        try (OutputStream outputStream = new FileOutputStream(randomName)) {
            // 配置水印内容
            WaterMark watermark = new WaterMark();
            String content = useName + useId;
            watermark.setContent(content);
            watermark.setWidth(400);
            watermark.setHeight(200);
            watermark.setYAxis(100);

            // 创建居中样式
            WriteCellStyle writeCellStyle = new WriteCellStyle();
            writeCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            writeCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            // 创建策略来应用样式
            WriteCellStyle cellStyle = new WriteCellStyle();
            cellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
            cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            WriteFont writeFont = new WriteFont();
            cellStyle.setWriteFont(writeFont);

            HorizontalCellStyleStrategy styleStrategy = new HorizontalCellStyleStrategy(cellStyle, cellStyle);


            // 使用 EasyExcel 写入数据
            ExcelWriter excelWriter = EasyExcel.write(outputStream).inMemory(true)
                    .registerWriteHandler(new WaterMarkHandler(watermark))
                    .registerWriteHandler(styleStrategy) // 全局居中
                    .build();

            for (int i = 0; i < data.size(); i++) {
                List<List<String>> sheetData = data.get(i);
                excelWriter.write(sheetData, EasyExcel.writerSheet("Sheet" + (i + 1)).build());
            }
            excelWriter.finish();
        } catch (Exception e) {
            LogUtil.error("文件添加水印和加密", String.format("生成文件地址, 文件名:%s, 操作者:%s", fileName, useId), null, e);
            throw new RuntimeException("生成并上传带水印的Excel文件时出错", e);
        }

        try (FileInputStream fis = new FileInputStream(randomName);
             Workbook workbook = WorkbookFactory.create(fis);

             FileOutputStream fos = new FileOutputStream(randomName)) {

            for (Map.Entry<Integer, List<CellRangeAddress>> entry : sheetMergedRegions.entrySet()) {
                Sheet sheet = workbook.getSheetAt(entry.getKey());

                // 设置单元格样式,内容居中
                CellStyle centeredStyle = workbook.createCellStyle();
                centeredStyle.setAlignment(HorizontalAlignment.CENTER);
                centeredStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                // 重新应用合并单元格并居中
                for (CellRangeAddress cellRangeAddress : entry.getValue()) {
                    sheet.addMergedRegion(cellRangeAddress);

                    // 对合并单元格的第一个单元格应用居中样式
                    Row row = sheet.getRow(cellRangeAddress.getFirstRow());
                    if (row != null) {
                        Cell cell = row.getCell(cellRangeAddress.getFirstColumn());
                        if (cell != null) {
                            cell.setCellStyle(centeredStyle);
                        }
                    }
                }

                // 根据内容自动调整列宽
                for (int colIndex = 0; colIndex < sheet.getRow(1).getPhysicalNumberOfCells(); colIndex++) {
                    sheet.autoSizeColumn(colIndex);
                    // 设置最大列宽限制,防止列宽过宽
                    int columnWidth = sheet.getColumnWidth(colIndex);
                    int maxColumnWidth = 6000; // 最大列宽
                    sheet.setColumnWidth(colIndex, maxColumnWidth);
                }
            }

            workbook.write(fos);

            // 加密文件并上传
            String password = useId + DateUtils.convertDate2Str(new Date(), DateUtils.FORMAT_DATA_COMPACT);
            FileUtils.encryptExcelFile(randomName, fileName, password);
            tempFile = new File(fileName);
            //使用minio 生成文件地址
            fileAddress = minioUtil.uploadFile(tempFile, "report");
        } catch (Exception e) {
            LogUtil.error("文件添加水印和加密", String.format("生成文件地址, 文件名:%s, 操作者:%s", fileName, useId), null, e);
            throw new RuntimeException("生成并上传带水印的Excel文件时出错", e);
        } finally {
            File file = new File(randomName);
            if(!file.delete()){
                LogUtil.info("文件添加水印和机密,文件删除失败", String.format("无法删除临时文件:%s", randomName), null);
            }
            if (tempFile != null && tempFile.exists()) {
                if(!tempFile.delete()){
                    LogUtil.info("文件添加水印和机密,文件删除失败", String.format("无法删除临时文件:%s", fileName), null);

                }
            }
        }
        return fileAddress;
    }
java 复制代码
   /**
     *
     * 从指定的 URL 下载文件并返回 InputStream
     * @param fileUrl 文件的 URL
     * @return InputStream 文件输入流
     * @throws IOException 如果发生网络或 IO 错误
     */
    private InputStream readFileStream(String fileUrl)  {
        try {
            // 创建 URL 对象
            URL url = new URL(fileUrl);
            // 打开连接并获取输入流
            URLConnection urlConnection = url.openConnection();
            InputStream inputStream = new BufferedInputStream(urlConnection.getInputStream());
            // 返回输入流
            return inputStream;
        } catch (IOException e) {
            LogUtil.error("报表数据提取", String.format("文件地址:%s", fileUrl), null, e);
            throw new BaseApiException(-1, "文件流读取失败");
        }
    }
相关推荐
tumeng07112 分钟前
Spring详解
java·后端·spring
深邃-9 分钟前
【Web安全】-基础环境安装:虚拟机安装,JDK环境安装(1)
java·开发语言·计算机网络·安全·web安全·网络安全·安全架构
小雅痞10 分钟前
[Java][Leetcode hard] 135. 分发糖果
java·算法·leetcode
q54314708712 分钟前
基于Spring Boot 3 + Spring Security6 + JWT + Redis实现登录、token身份认证
spring boot·redis·spring
jwt79392793716 分钟前
Spring之DataSource配置
java·后端·spring
逻辑驱动的ken24 分钟前
Java高频面试场景题07
java·开发语言·面试·职场和发展·求职招聘·春招
slarymusic29 分钟前
解决报错net.sf.jsqlparser.statement.select.SelectBody
java
callJJ31 分钟前
JVM 内存区域划分详解——从生活比喻到运行时数据区全景图
java·jvm·面试·内存区域划分
小江的记录本35 分钟前
【网络安全】《网络安全与数据安全核心知识体系》(包括数据脱敏、数据加密、隐私合规、等保2.0)
java·网络·后端·python·算法·安全·web安全
北漂Zachary35 分钟前
PHP vs Python vs Java:三大编程语言终极对比
java·python·php