文件批量添加水印和密码合并单元格完整版
这段代码是一个 Java 方法,用于向文件添加水印和密码。您解释一下:
首先,它接受一个 fileAddress 参数,表示文件的地址。
然后,它创建了一个线程安全的列表 fileDatas,用于存储文件数据。
接下来,它尝试读取文件流,并获取所有 sheet 的数据。
在循环中,它逐个读取每个 sheet 的数据,并将其添加到 fileDatas 列表中。
如果在读取数据时发生异常,它会记录错误并抛出运行时异常。
最后,它生成一个新的文件名 newFileName,并使用 generationFileAddress 方法生成带有水印和密码的文件地址。
请注意,代码中的一些变量(例如 fileUrl、dto)在这里没有定义,您需要根据您的实际情况进行替换。如果您有其他问题或需要更详细的解释,请随时告知!😊
/**
*文件添加水印密码
*/
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;
}
/**
* 处理合并单元格为空处理
*/
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;
}
/**
* 计算每个单元格的值
*/
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 "";
}
}
/**
* 生成文件地址
* @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;
}
/**
*
* 从指定的 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, "文件流读取失败");
}
}