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

news/2024/9/21 4:23:42 标签: java, ide, spring

这段代码是一个 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, "文件流读取失败");
        }
    }

http://www.niftyadmin.cn/n/5668132.html

相关文章

NFT Insider #148:The Sandbox 推出 SHIBUYA Y3K 时尚系列,Azuki 进军动漫 NFT 领域

市场数据 加密艺术及收藏品新闻 Infinex 新推 NFT 系列首四日销售额破4000万美元 尽管顶级 NFT 系列表现不佳&#xff0c;Infinex 的最新 NFT 系列在首四日内销售额已超过 4000 万美元。Infinex 是一个非托管平台&#xff0c;提供轻松访问链上协议和 dApp。 Infinex Core 的…

5G 扬帆新质跃,技术蝶变开新篇-第七届“绽放杯”5G应用征集大赛 5G应用融合技术专题赛圆满收官

2024年9月13日,由中国信息通信研究院、中国电信集团有限公司、中国移动通信集团有限公司、中国联合网络通信集团有限公司主办,5G应用产业方阵承办的第七届“绽放杯”5G应用征集大赛  5G应用融合技术专题赛决赛在深圳成功举办。 本次专题赛以“5G扬帆新质跃,技术蝶变开新篇”为…

Python学习的主要知识框架

Python的主要学习知识点非常广泛且深入&#xff0c;但我可以为您概括一些核心的学习领域&#xff0c;帮助您系统地掌握Python编程。以下是Python学习的主要知识框架&#xff1a; 1. Python基础语法 数据类型&#xff1a;整数、浮点数、字符串、布尔值、列表、元组、字典、集合…

Android文件系统的结构及目录用途、操作方法

Android文件系统的结构可以分为以下几个主要目录&#xff1a; /system&#xff1a;该目录包含Android操作系统核心文件&#xff0c;例如系统应用程序和库文件。一般情况下&#xff0c;此目录只能读取&#xff0c;无法写入。 /data&#xff1a;该目录用于存储应用程序的数据&am…

网站性能优化:如何高效预加载大型静态资源

网站性能优化&#xff1a;如何高效预加载大型静态资源 在开发中&#xff0c;面对大型文件&#xff0c;尤其是涉及炫酷动效的场景&#xff0c;如何高效加载资源是提升用户体验的关键。针对大文件的加载优化&#xff0c;推测性加载机制可以显著提高网页的响应速度和流畅度。本文…

web worker使用

1. 新建worker.js import kriging from "/views/Heatmap/kriging";self.onmessage (e) > {console.log(e) // 主线程传过来的数据self.postMessage(我是子线程的数据) // 返回给主线程的数据 }2. 在使用的文件引入woker.js 注&#xff1a; 在worker中如果要使用…

在系统总线的数据线上,不可能传输的是()。

在系统总线的数据线上&#xff0c;不可能传输的是 A&#xff0e;指令 B&#xff0e;操作数 C&#xff0e;握手&#xff08;应答&#xff09;信号 D&#xff0e;中断类型号 答案&#xff1a;在系统总线的数据线上&#xff0c;不可能传输的是&#xff1a; C. 握手&#xff08;应…

Linux 进程3

进程地址空间 CPU读取数据都需要地址&#xff0c;在计算机中所有东西都是一种数据&#xff0c;包括我们的进程。 这是一个进程空间示意图&#xff0c;操作系统通过task_struct结构体链表来管理每一个进程&#xff0c;结构体里面有一个指针指向操作系统为进程开辟的一段空间&am…