excel轉pdf并且加水印,利用ByteArrayOutputStream內存流不產生中間文件

首先先引入包:加水印和excel轉PDF的

    <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.12</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version> <!-- 版本號根據您實際使用的版本進行調整 --></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version> <!-- 根據實際需要選擇版本號 --></dependency>

然后兩個工具類,第一個是加水印的

package org.springblade.common.tool;import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;import java.io.*;
import java.util.List;public class PDFWatermarkExample {public static void addWatermark(String inputFile, String outputFile, String watermarkText) {try {PdfReader reader = new PdfReader(inputFile);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));int numberOfPages = reader.getNumberOfPages();for (int i = 1; i <= numberOfPages; i++) {PdfContentByte content = stamper.getUnderContent(i);PdfGState gs = new PdfGState();gs.setFillOpacity(0.5f); // 設置水印透明度content.setGState(gs);ColumnText.showTextAligned(content,Element.ALIGN_CENTER,new Phrase(watermarkText, new Font(Font.FontFamily.HELVETICA, 40)),reader.getPageSizeWithRotation(i).getWidth() / 2,reader.getPageSizeWithRotation(i).getHeight() / 2,45);}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();}}public static void addWatermarkMulti(String inputFile, String outputFile, String watermarkText) {try {PdfReader reader = new PdfReader(inputFile);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));int numberOfPages = reader.getNumberOfPages();for (int i = 1; i <= numberOfPages; i++) {PdfContentByte content = stamper.getOverContent(i);PdfGState gs = new PdfGState();gs.setFillOpacity(0.5f); // 設置水印透明度content.setGState(gs);Rectangle pageSize = reader.getPageSizeWithRotation(i);float pageWidth = pageSize.getWidth();float pageHeight = pageSize.getHeight();// 設置水印間隔float xInterval = 200; // X軸間隔float yInterval = 50; // Y軸間隔// 計算水印個數int xCount = (int) Math.ceil(pageWidth / xInterval);int yCount = (int) Math.ceil(pageHeight / yInterval);// 平鋪水印for (int x = 0; x < xCount; x++) {for (int y = 0; y < yCount; y++) {float xPosition = x * xInterval;float yPosition = y * yInterval;ColumnText.showTextAligned(content,Element.ALIGN_CENTER,new Phrase(watermarkText, new Font(Font.FontFamily.HELVETICA, 40)),xPosition,yPosition,45);}}}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();}}public static void addWatermarkMultiCN(String inputFile, String outputFile, String watermarkText) {try {PdfReader reader = new PdfReader(inputFile);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));int numberOfPages = reader.getNumberOfPages();Resource resource = new ClassPathResource("simhei.ttf"); // 加載位于resources目錄下的字體文件InputStream inputStream = resource.getInputStream();byte[] fontBytes = IOUtils.toByteArray(inputStream);BaseFont baseFont = BaseFont.createFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, fontBytes, null); // 創建BaseFont對象for (int i = 1; i <= numberOfPages; i++) {PdfContentByte content = stamper.getOverContent(i);PdfGState gs = new PdfGState();gs.setFillOpacity(0.5f); // 設置水印透明度content.setGState(gs);Rectangle pageSize = reader.getPageSizeWithRotation(i);float pageWidth = pageSize.getWidth();float pageHeight = pageSize.getHeight();// 設置水印間隔float xInterval = 200; // X軸間隔float yInterval = 50; // Y軸間隔// 計算水印個數int xCount = (int) Math.ceil(pageWidth / xInterval);int yCount = (int) Math.ceil(pageHeight / yInterval);// 平鋪水印for (int x = 0; x < xCount; x++) {for (int y = 0; y < yCount; y++) {float xPosition = x * xInterval;float yPosition = y * yInterval;ColumnText.showTextAligned(content,Element.ALIGN_CENTER,new Phrase(watermarkText, new Font(baseFont, 40)), // 使用創建的中文字體xPosition,yPosition,45);}}}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();}}/**** @param inputStream  文件輸入流* @param watermarkText  水印文字* @return*/public static ByteArrayOutputStream addWatermarkToPdfStream(InputStream inputStream, String watermarkText) {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try {PdfReader reader = new PdfReader(inputStream);PdfStamper stamper = new PdfStamper(reader, outputStream);int numberOfPages = reader.getNumberOfPages();// ...(原有的水印添加邏輯)Resource resource = new ClassPathResource("simhei.ttf"); // 加載位于resources目錄下的字體文件InputStream inputStreamTTF = resource.getInputStream();byte[] fontBytes = IOUtils.toByteArray(inputStreamTTF);BaseFont baseFont = BaseFont.createFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, true, fontBytes, null); // 創建BaseFont對象for (int i = 1; i <= numberOfPages; i++) {PdfContentByte content = stamper.getOverContent(i);PdfGState gs = new PdfGState();gs.setFillOpacity(0.3f); // 設置水印透明度content.setGState(gs);Rectangle pageSize = reader.getPageSizeWithRotation(i);float pageWidth = pageSize.getWidth();float pageHeight = pageSize.getHeight();// 設置水印間隔float xInterval = 400; // X軸間隔float yInterval = 150; // Y軸間隔// 計算水印個數int xCount = (int) Math.ceil(pageWidth / xInterval);int yCount = (int) Math.ceil(pageHeight / yInterval);// 平鋪水印for (int x = 0; x < xCount; x++) {for (int y = 0; y < yCount; y++) {float xPosition = x * xInterval;float yPosition = y * yInterval;ColumnText.showTextAligned(content,Element.ALIGN_CENTER,new Phrase(watermarkText, new Font(baseFont, 20)), // 使用創建的中文字體xPosition,yPosition,45);}}}stamper.close();reader.close();} catch (Exception e) {e.printStackTrace();}return outputStream;}public static void addWatermarkExample(List<File> files) {// 在這里編寫添加水印的代碼邏輯,使用上面提到的添加水印的示例代碼for (File file : files) {addWatermark(file.getPath(), file.getPath(), "Watermark Text");}}public static void main(String[] args) {String inputFile = "D:\\Downloads\\123.pdf";String outputFile = "D:\\Downloads\\456.pdf";String watermarkText = "這是中文水印";addWatermarkMultiCN(inputFile, outputFile, watermarkText);String outputFileStream = "D:\\Downloads\\789.pdf";String watermarkText02 = "這是讀取流返回流";try (InputStream input = new FileInputStream(inputFile)) {ByteArrayOutputStream output = addWatermarkToPdfStream(input, watermarkText02);try (OutputStream fileOutput = new FileOutputStream(outputFileStream)) {output.writeTo(fileOutput);}} catch (IOException e) {e.printStackTrace();}}
}

別忘記字體在resource里面讀取的

第二個是轉PDF的

package org.springblade.common.tool;import cn.hutool.core.collection.CollUtil;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.experimental.UtilityClass;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;@UtilityClass
public class ExcelToPdfUtil {public static void excelToPdf(String excelPath, String pdfPath, String excelSuffix) {try (InputStream in = Files.newInputStream(Paths.get(excelPath));OutputStream out = Files.newOutputStream(Paths.get(pdfPath))) {ExcelToPdfUtil.excelToPdf(in, out, excelSuffix);} catch (Exception e) {e.printStackTrace();}}/*** Excel轉PDF并寫入輸出流** @param inStream    Excel輸入流* @param outStream   PDF輸出流* @param excelSuffix Excel類型 .xls 和 .xlsx* @throws Exception 異常信息*/public static void excelToPdf(InputStream inStream, OutputStream outStream, String excelSuffix) throws Exception {// 輸入流轉workbook,獲取sheetSheet sheet = getPoiSheetByFileStream(inStream, 0, excelSuffix);// 獲取列寬度占比float[] widths = getColWidth(sheet);PdfPTable table = new PdfPTable(widths);table.setWidthPercentage(100);int colCount = widths.length;//設置基本字體BaseFont baseFont = BaseFont.createFont("C:\\Windows\\Fonts\\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);// 遍歷行for (int rowIndex = sheet.getFirstRowNum(); rowIndex <= sheet.getLastRowNum(); rowIndex++) {Row row = sheet.getRow(rowIndex);if (Objects.isNull(row)) {// 插入空對象for (int i = 0; i < colCount; i++) {table.addCell(createPdfPCell(null, 0, 13f, null));}} else {// 遍歷單元格for (int columnIndex = 0; (columnIndex < row.getLastCellNum() || columnIndex < colCount) && columnIndex > -1; columnIndex++) {PdfPCell pCell = excelCellToPdfCell(sheet, row.getCell(columnIndex), baseFont);// 是否合并單元格if (isMergedRegion(sheet, rowIndex, columnIndex)) {int[] span = getMergedSpan(sheet, rowIndex, columnIndex);//忽略合并過的單元格boolean mergedCell = span[0] == 1 && span[1] == 1;if (mergedCell) {continue;}pCell.setRowspan(span[0]);pCell.setColspan(span[1]);}table.addCell(pCell);}}}// 初始化PDF文檔對象createPdfTableAndWriteDocument(outStream, table);}/*** 單元格轉換,poi cell 轉換為 itext cell** @param sheet     poi sheet頁* @param excelCell poi 單元格* @param baseFont  基礎字體* @return com.itextpdf.text.pdf.PdfPCell*/private static PdfPCell excelCellToPdfCell(Sheet sheet, Cell excelCell, BaseFont baseFont) throws Exception {if (Objects.isNull(excelCell)) {return createPdfPCell(null, 0, 13f, null);}int rowIndex = excelCell.getRowIndex();int columnIndex = excelCell.getColumnIndex();// 圖片信息List<PicturesInfo> infos = getAllPictureInfos(sheet, rowIndex, rowIndex, columnIndex, columnIndex, false);PdfPCell pCell;if (CollUtil.isNotEmpty(infos)) {pCell = new PdfPCell(Image.getInstance(infos.get(0).getPictureData()));} else {Font excelFont = getExcelFont(sheet, excelCell);//設置單元格字體com.itextpdf.text.Font pdFont = new com.itextpdf.text.Font(baseFont, excelFont.getFontHeightInPoints(), excelFont.getBold() ? 1 : 0, BaseColor.BLACK);Integer border = hasBorder(excelCell) ? null : 0;String excelCellValue = getExcelCellValue(excelCell);pCell = createPdfPCell(excelCellValue, border, excelCell.getRow().getHeightInPoints(), pdFont);}// 水平居中pCell.setHorizontalAlignment(getHorAlign(excelCell.getCellStyle().getAlignment().getCode()));// 垂直對齊pCell.setVerticalAlignment(getVerAlign(excelCell.getCellStyle().getVerticalAlignment().getCode()));return pCell;}/*** 創建pdf文檔,并添加表格** @param outStream 輸出流,目標文檔* @param table     表格* @throws DocumentException 異常信息*/private static void createPdfTableAndWriteDocument(OutputStream outStream, PdfPTable table) throws DocumentException {//設置pdf紙張大小 PageSize.A4 A4橫向Document document = new Document(new RectangleReadOnly(842.0F, 595.0F));PdfWriter.getInstance(document, outStream);//設置頁邊距 寬document.setMargins(10, 10, 10, 10);document.open();document.add(table);document.close();}/*** Excel文檔輸入流轉換為對應的workbook及獲取對應的sheet** @param inputStream Excel文檔輸入流* @param sheetNo     sheet編號,默認0 第一個sheet* @param excelSuffix 文件類型 .xls和.xlsx* @return poi sheet* @throws IOException 異常*/public static Sheet getPoiSheetByFileStream(InputStream inputStream, int sheetNo, String excelSuffix) throws IOException {Workbook workbook;if (excelSuffix.endsWith(".xls")) {workbook = new HSSFWorkbook(inputStream);} else {workbook = new XSSFWorkbook(inputStream);}return workbook.getSheetAt(sheetNo);}/*** 創建itext pdf 單元格** @param content       單元格內容* @param border        邊框* @param minimumHeight 高度* @param pdFont        字體* @return pdf cell*/private static PdfPCell createPdfPCell(String content, Integer border, Float minimumHeight, com.itextpdf.text.Font pdFont) {String contentValue = content == null ? "" : content;com.itextpdf.text.Font pdFontNew = pdFont == null ? new com.itextpdf.text.Font() : pdFont;PdfPCell pCell = new PdfPCell(new Phrase(contentValue, pdFontNew));if (Objects.nonNull(border)) {pCell.setBorder(border);}if (Objects.nonNull(minimumHeight)) {pCell.setMinimumHeight(minimumHeight);}return pCell;}/*** excel垂直對齊方式映射到pdf對齊方式*/private static int getVerAlign(int align) {switch (align) {case 2:return com.itextpdf.text.Element.ALIGN_BOTTOM;case 3:return com.itextpdf.text.Element.ALIGN_TOP;default:return com.itextpdf.text.Element.ALIGN_MIDDLE;}}/*** excel水平對齊方式映射到pdf水平對齊方式*/private static int getHorAlign(int align) {switch (align) {case 1:return com.itextpdf.text.Element.ALIGN_LEFT;case 3:return com.itextpdf.text.Element.ALIGN_RIGHT;default:return com.itextpdf.text.Element.ALIGN_CENTER;}}/*============================================== POI獲取圖片及文本內容工具方法 ==============================================*//*** 獲取字體** @param sheet excel 轉換的sheet頁* @param cell  單元格* @return 字體*/private static Font getExcelFont(Sheet sheet, Cell cell) {// xlsif (sheet instanceof HSSFSheet) {Workbook workbook = sheet.getWorkbook();return ((HSSFCell) cell).getCellStyle().getFont(workbook);}// xlsxreturn ((XSSFCell) cell).getCellStyle().getFont();}/*** 判斷excel單元格是否有邊框*/private static boolean hasBorder(Cell excelCell) {short top = excelCell.getCellStyle().getBorderTop().getCode();short bottom = excelCell.getCellStyle().getBorderBottom().getCode();short left = excelCell.getCellStyle().getBorderLeft().getCode();short right = excelCell.getCellStyle().getBorderRight().getCode();return top + bottom + left + right > 2;}/*** 判斷單元格是否是合并單元格*/private static boolean isMergedRegion(Sheet sheet, int row, int column) {int sheetMergeCount = sheet.getNumMergedRegions();for (int i = 0; i < sheetMergeCount; i++) {CellRangeAddress range = sheet.getMergedRegion(i);int firstColumn = range.getFirstColumn();int lastColumn = range.getLastColumn();int firstRow = range.getFirstRow();int lastRow = range.getLastRow();if (row >= firstRow && row <= lastRow) {if (column >= firstColumn && column <= lastColumn) {return true;}}}return false;}/*** 計算合并單元格合并的跨行跨列數*/private static int[] getMergedSpan(Sheet sheet, int row, int column) {int sheetMergeCount = sheet.getNumMergedRegions();int[] span = {1, 1};for (int i = 0; i < sheetMergeCount; i++) {CellRangeAddress range = sheet.getMergedRegion(i);int firstColumn = range.getFirstColumn();int lastColumn = range.getLastColumn();int firstRow = range.getFirstRow();int lastRow = range.getLastRow();if (firstColumn == column && firstRow == row) {span[0] = lastRow - firstRow + 1;span[1] = lastColumn - firstColumn + 1;break;}}return span;}/*** 獲取excel中每列寬度的占比*/private static float[] getColWidth(Sheet sheet) {int rowNum = getMaxColRowNum(sheet);Row row = sheet.getRow(rowNum);int cellCount = row.getPhysicalNumberOfCells();int[] colWidths = new int[cellCount];int sum = 0;for (int i = row.getFirstCellNum(); i < cellCount; i++) {Cell cell = row.getCell(i);if (cell != null) {colWidths[i] = sheet.getColumnWidth(i);sum += sheet.getColumnWidth(i);}}float[] colWidthPer = new float[cellCount];for (int i = row.getFirstCellNum(); i < cellCount; i++) {colWidthPer[i] = (float) colWidths[i] / sum * 100;}return colWidthPer;}/*** 獲取excel中列數最多的行號*/private static int getMaxColRowNum(Sheet sheet) {int rowNum = 0;int maxCol = 0;for (int r = sheet.getFirstRowNum(); r < sheet.getPhysicalNumberOfRows(); r++) {Row row = sheet.getRow(r);if (row != null && maxCol < row.getPhysicalNumberOfCells()) {maxCol = row.getPhysicalNumberOfCells();rowNum = r;}}return rowNum;}/*** poi 根據單元格類型獲取單元格內容** @param excelCell poi單元格* @return 單元格內容文本*/public static String getExcelCellValue(Cell excelCell) {if (excelCell == null) {return "";}// 判斷數據的類型CellType cellType = excelCell.getCellType();if (cellType == CellType.STRING) {return excelCell.getStringCellValue();}if (cellType == CellType.BOOLEAN) {return String.valueOf(excelCell.getBooleanCellValue());}if (cellType == CellType.FORMULA) {return excelCell.getCellFormula();}if (cellType == CellType.NUMERIC) {//short s = excelCell.getCellStyle().getDataFormat();if (DateUtil.isCellDateFormatted(excelCell)) {// 處理日期格式、時間格式SimpleDateFormat sdf;// 驗證short值if (excelCell.getCellStyle().getDataFormat() == 14) {sdf = new SimpleDateFormat("yyyy/MM/dd");} else if (excelCell.getCellStyle().getDataFormat() == 21) {sdf = new SimpleDateFormat("HH:mm:ss");} else if (excelCell.getCellStyle().getDataFormat() == 22) {sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");} else {throw new RuntimeException("日期格式錯誤!!!");}Date date = excelCell.getDateCellValue();return sdf.format(date);} else if (excelCell.getCellStyle().getDataFormat() == 0) {//處理數值格式DataFormatter formatter = new DataFormatter();return formatter.formatCellValue(excelCell);}}if (cellType == CellType.ERROR) {return "非法字符";}return "";}/*** 獲取sheet內的所有圖片信息** @param sheet        sheet表* @param onlyInternal 單元格內部* @return 照片集合* @throws Exception 異常*/public static List<PicturesInfo> getAllPictureInfos(Sheet sheet, boolean onlyInternal) throws Exception {return getAllPictureInfos(sheet, null, null, null, null, onlyInternal);}/*** 根據sheet和單元格信息獲取圖片** @param sheet        sheet表* @param minRow       最小行* @param maxRow       最大行* @param minCol       最小列* @param maxCol       最大列* @param onlyInternal 是否內部* @return 圖片集合* @throws Exception 異常*/public static List<PicturesInfo> getAllPictureInfos(Sheet sheet, Integer minRow, Integer maxRow, Integer minCol,Integer maxCol, boolean onlyInternal) throws Exception {if (sheet instanceof HSSFSheet) {return getXLSAllPictureInfos((HSSFSheet) sheet, minRow, maxRow, minCol, maxCol, onlyInternal);} else if (sheet instanceof XSSFSheet) {return getXLSXAllPictureInfos((XSSFSheet) sheet, minRow, maxRow, minCol, maxCol, onlyInternal);} else {throw new Exception("未處理類型,沒有為該類型添加:GetAllPicturesInfos()擴展方法!");}}private static List<PicturesInfo> getXLSAllPictureInfos(HSSFSheet sheet, Integer minRow, Integer maxRow,Integer minCol, Integer maxCol, Boolean onlyInternal) {List<PicturesInfo> picturesInfoList = new ArrayList<>();HSSFShapeContainer shapeContainer = sheet.getDrawingPatriarch();if (shapeContainer == null) {return picturesInfoList;}List<HSSFShape> shapeList = shapeContainer.getChildren();for (HSSFShape shape : shapeList) {if (shape instanceof HSSFPicture && shape.getAnchor() instanceof HSSFClientAnchor) {HSSFPicture picture = (HSSFPicture) shape;HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),anchor.getCol1(), anchor.getCol2(), onlyInternal)) {HSSFPictureData pictureData = picture.getPictureData();picturesInfoList.add(new PicturesInfo().setMinRow(anchor.getRow1()).setMaxRow(anchor.getRow2()).setMinCol(anchor.getCol1()).setMaxCol(anchor.getCol2()).setPictureData(pictureData.getData()).setExt(pictureData.getMimeType()));}}}return picturesInfoList;}private static List<PicturesInfo> getXLSXAllPictureInfos(XSSFSheet sheet, Integer minRow, Integer maxRow,Integer minCol, Integer maxCol, Boolean onlyInternal) {List<PicturesInfo> picturesInfoList = new ArrayList<>();List<POIXMLDocumentPart> documentPartList = sheet.getRelations();for (POIXMLDocumentPart documentPart : documentPartList) {if (documentPart instanceof XSSFDrawing) {XSSFDrawing drawing = (XSSFDrawing) documentPart;List<XSSFShape> shapes = drawing.getShapes();for (XSSFShape shape : shapes) {if (shape instanceof XSSFPicture) {XSSFPicture picture = (XSSFPicture) shape;XSSFClientAnchor anchor = picture.getPreferredSize();if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),anchor.getCol1(), anchor.getCol2(), onlyInternal)) {XSSFPictureData pictureData = picture.getPictureData();picturesInfoList.add(new PicturesInfo().setMinRow(anchor.getRow1()).setMaxRow(anchor.getRow2()).setMinCol(anchor.getCol1()).setMaxCol(anchor.getCol2()).setPictureData(pictureData.getData()).setExt(pictureData.getMimeType()));}}}}}return picturesInfoList;}private static boolean isInternalOrIntersect(Integer rangeMinRow, Integer rangeMaxRow, Integer rangeMinCol,Integer rangeMaxCol, int pictureMinRow, int pictureMaxRow, int pictureMinCol, int pictureMaxCol,Boolean onlyInternal) {int _rangeMinRow = rangeMinRow == null ? pictureMinRow : rangeMinRow;int _rangeMaxRow = rangeMaxRow == null ? pictureMaxRow : rangeMaxRow;int _rangeMinCol = rangeMinCol == null ? pictureMinCol : rangeMinCol;int _rangeMaxCol = rangeMaxCol == null ? pictureMaxCol : rangeMaxCol;if (onlyInternal) {return (_rangeMinRow <= pictureMinRow && _rangeMaxRow >= pictureMaxRow && _rangeMinCol <= pictureMinCol&& _rangeMaxCol >= pictureMaxCol);} else {return ((Math.abs(_rangeMaxRow - _rangeMinRow) + Math.abs(pictureMaxRow - pictureMinRow) >= Math.abs(_rangeMaxRow + _rangeMinRow - pictureMaxRow - pictureMinRow))&& (Math.abs(_rangeMaxCol - _rangeMinCol) + Math.abs(pictureMaxCol - pictureMinCol) >= Math.abs(_rangeMaxCol + _rangeMinCol - pictureMaxCol - pictureMinCol)));}}/*** 圖片基本信息*/private class PicturesInfo {private int minRow;private int maxRow;private int minCol;private int maxCol;private String ext;private byte[] pictureData;public PicturesInfo() {}public byte[] getPictureData() {return pictureData;}public PicturesInfo setPictureData(byte[] pictureData) {this.pictureData = pictureData;return this;}public int getMinRow() {return minRow;}public PicturesInfo setMinRow(int minRow) {this.minRow = minRow;return this;}public int getMaxRow() {return maxRow;}public PicturesInfo setMaxRow(int maxRow) {this.maxRow = maxRow;return this;}public int getMinCol() {return minCol;}public PicturesInfo setMinCol(int minCol) {this.minCol = minCol;return this;}public int getMaxCol() {return maxCol;}public PicturesInfo setMaxCol(int maxCol) {this.maxCol = maxCol;return this;}public String getExt() {return ext;}public PicturesInfo setExt(String ext) {this.ext = ext;return this;}//有中間文件的 excel轉pdf再加水印
//		public static void main(String[] args) throws FileNotFoundException {
//			String inputFile = "D:\\Downloads\\123.xlsx";
//			String outputFile = "D:\\Downloads\\999.pdf";
//			String watermarkedFile = "D:\\Downloads\\999_watermarked.pdf";
//
//			// 獲取inputFile的文件輸出流
//			FileInputStream fileInputStream = new FileInputStream(inputFile);
//
//			try {
//				// 創建輸出流
//				OutputStream outputStream = new FileOutputStream(outputFile);
//
//				// 調用excelToPdf方法將Excel轉換為PDF并寫入輸出流
//				excelToPdf(fileInputStream, outputStream, "xlsx");
//
//				//這個outputStream將里面的數據轉成inputStream,后續要再做一次處理
//
//
//				// 關閉輸入流和輸出流
//				fileInputStream.close();
//
//				//==============================加水印=================================
//				// 創建輸入流和輸出流
//				FileInputStream pdfInputStream = new FileInputStream(outputFile);
//				ByteArrayOutputStream watermarkedOutputStream = PDFWatermarkExample.addWatermarkToPdfStream(pdfInputStream, "excel轉PDF再加水印");
//
//				// 將加水印后的PDF寫入文件
//				FileOutputStream watermarkedFileOutputStream = new FileOutputStream(watermarkedFile);
//				watermarkedOutputStream.writeTo(watermarkedFileOutputStream);
//
//				// 關閉輸入流和輸出流
//				pdfInputStream.close();
//				watermarkedOutputStream.close();
//				watermarkedFileOutputStream.close();
//
//
//				outputStream.close();
//			} catch (Exception e) {
//				e.printStackTrace();
//			}
//		}/*** 通過使用內存流,可以直接從Excel文件轉換為帶水印的PDF文件,而不需要生成中間文件。* @param args* @throws FileNotFoundException*/public static void main(String[] args) throws FileNotFoundException {String inputFile = "D:\\Downloads\\123.xlsx";String watermarkedFile = "D:\\Downloads\\999_watermarked.pdf";try {// 創建輸入流FileInputStream fileInputStream = new FileInputStream(inputFile);// 創建輸出流ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();// 調用excelToPdf方法將Excel轉換為PDF并寫入輸出流excelToPdf(fileInputStream, pdfOutputStream, "xlsx");// 關閉輸入流fileInputStream.close();//==============================加水印=================================// 創建輸入流ByteArrayInputStream pdfInputStream = new ByteArrayInputStream(pdfOutputStream.toByteArray());ByteArrayOutputStream watermarkedOutputStream = PDFWatermarkExample.addWatermarkToPdfStream(pdfInputStream, "excel轉PDF再加水印");// 將加水印后的PDF寫入文件FileOutputStream watermarkedFileOutputStream = new FileOutputStream(watermarkedFile);watermarkedOutputStream.writeTo(watermarkedFileOutputStream);// 關閉輸入流和輸出流pdfInputStream.close();watermarkedOutputStream.close();watermarkedFileOutputStream.close();} catch (Exception e) {e.printStackTrace();}}}
}

最后的代碼就是通過內存流做的,避免中間文件。哎 寫這個真是麻煩

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13641.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13641.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13641.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2024全新爆款好物推薦,618必買數碼好物清單吐血整理!

?距離618購物狂歡節越來越近了&#xff0c;有很多日常價格不菲的產品在這次活動期間都會進行促銷活動&#xff0c;尤其是數碼類產品&#xff0c;加上618的優惠活動更有吸引力了。不過面對大促的熱潮我們消費者在選購商品的同時還是要擦亮眼睛&#xff0c;避免買到質量不好的商…

SSE 與 SASE哪個云原生安全框架更加適合

近年來&#xff0c;隨著云計算和網絡技術的不斷發展&#xff0c;出現了一種新的網絡安全解決方案——SASE&#xff08;安全訪問服務邊緣&#xff09;。SASE是一種將網絡和安全功能融合到單個基于云的服務中的框架&#xff0c;旨在提供更加安全、高效和便捷的網絡訪問體驗。SASE…

云原生周刊:Flux 2.3 發布 | 2024.5.20

開源項目推薦 kubeinvaders kubeinvaders 專為 Kubernetes 用戶設計。它提供了一種有趣而交互式的方式來探索和可視化您的 Kubernetes 集群。通過類似游戲的界面&#xff0c;用戶可以瀏覽他們的集群&#xff0c;發現資源&#xff0c;甚至模擬對 Pod 的攻擊。通過 kubeinvader…

我的前端封裝之路

最近有粉絲提問了我一個面試中遇到的問題&#xff0c;他說面試的時候&#xff0c;面試官問我&#xff1a;你在以前的項目中封裝過組件嗎&#xff1f;或者做過npm公共庫嗎&#xff1f;遇到過什么問題嗎&#xff1f;當時自己突然覺得好像沒什么可回答的啊&#xff0c;但面試結束想…

前端 CSS 經典:弧形邊框選項卡

1. 效果圖 2. 開始 準備一個元素&#xff0c;將元素左上角&#xff0c;右上角設為圓角。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, i…

thingML的學習——什么是thingML

今天開始建模的學習&#xff0c;thingML是建模的一種工具 &#xff0c;也可以理解為一種建模語言&#xff0c;有自己的語法和語義。 ThingML 支持的多種平臺和通信協議&#xff0c;如UART、I2C、MQTT、WebSocket、REST、ROS、Bluetooth、BLE和Zwave&#xff0c;通過插件機制&a…

Spring Cloud Alibaba-07-RocketMQ消息驅動

Lison <dreamlison163.com>, v1.0.0, 2024.4.20 Spring Cloud Alibaba-07-RocketMQ消息驅動 文章目錄 Spring Cloud Alibaba-07-RocketMQ消息驅動MQ簡介MQ的應用場景常見的MQ產品RocketeMQ的架構及概念 RocketMQ入門RocketMQ環境搭建 SpringBoot 集成 RocketMQ MQ簡介 …

來盤點我的校園生活(3)

來公布上期數學題答案:12 你算對了嗎&#xff1f; 今天我們班真是炸開了鍋。事情是這樣的&#xff0c;我今天早晨上學&#xff0c;學校不讓早到&#xff0c;但我一個不小心早到了&#xff0c;主任的規定是盡量不早到&#xff0c;早到不扣分&#xff0c;倒要站在那兒背書&…

Linux--軟硬鏈接

目錄 0.文件系統 1.軟硬鏈接 1.1見一下軟硬鏈接 1.2軟硬鏈接的特征 1.3軟硬鏈接是什么&#xff0c;有什么作用&#xff08;場景&#xff09; 0.文件系統 Linux--文件系統-CSDN博客 1.軟硬鏈接 1.1見一下軟硬鏈接 1.這是軟鏈接 這個命令在Unix和Linux系統中用于創建一個符號…

基于 Prometheus 的超算彈性計算場景下主機監控最佳實踐

作者&#xff1a;左知 超算場景的業務特點 主機監控&#xff0c;或許是監控/可觀測領域最傳統和普遍的需求。在超算訓練&#xff0c;AI 大規模訓練的業務場景下&#xff0c;主機監控又有哪些痛點和難點呢&#xff1f;根據我們針對多個大規模超算客戶的需求整理&#xff0c;超…

Python案例題目,入門小白題

1.抓取鏈家前十頁的數據 鏈家網址&#xff1a;長沙房產網_長沙房地產_長沙房產門戶(長沙鏈家網) 1.1.計算均價和總價 import time ? from selenium import webdriver from selenium.webdriver.common.by import By ? driver webdriver.Chrome() driver.get("https://c…

linux系統內存持續飆高的排查方法

目錄 前言&#xff1a; 1、查看系統內存的占用情況 2、找出占用內存高的進程 3、解決方法 4、補充&#xff1a;如果物理內存使用完了&#xff0c;會發生的情況 前言&#xff1a; 如果一臺服務器內存使用率持續處于一個高峰值&#xff0c;服務器可能會出現響應慢問題。例如s…

使用@Autowired + Map 實現策略模式

使用Autowired Map 實現策略模式 創建接口 public interface UserService {String getName(); }創建多個類實現上面的接口 實現一 import com.boot.service.UserService; import org.springframework.stereotype.Service;Service("zhangsan") public class Zhangsan…

代碼隨想錄算法訓練營第十六天|LeetCode104 二叉樹的最大深度、LeetCode111 二叉樹的最小深度、LeetCode222完全二叉樹的節點個數

題1&#xff1a; 指路&#xff1a;LeetCode104 二叉樹的最大深度 思路與代碼&#xff1a; 1.遞歸 求左右子樹的最大深度后加1(根到子樹也有1個深度單位)。代碼如下&#xff1a; class Solution { public:int maxDepth(TreeNode* root) {int ans 0;if (root NULL) return…

當他們在說業務的時候,到底在說什么

業務就是通過提供產品和服務給客戶&#xff0c;以獲取某種價值&#xff0c;形成業務閉環&#xff0c;并能自負盈虧。 文章會以生動形象的比喻來介紹業務到底是什么。 什么是業務&#xff1f; 業務&#xff0c;就像一場精彩的舞臺劇&#xff0c;每個角色都有自己的任務和目標…

electron學習記錄

1.下載electron electron/electron-quick-start: Clone to try a simple Electron app (github.com) 下載實例模板 2.安裝依賴 npm源改成中國鏡像 npm config set registry https://registry.npmmirror.com 然后用cnpm i 來安裝 npm換官方源 npm config set registry https:…

QT--TCP網絡通訊工具編寫記錄

QT–TCP網絡通訊工具編寫記錄 文章目錄 QT--TCP網絡通訊工具編寫記錄前言演示如下&#xff1a;一、服務端項目文件&#xff1a;【1.1】server_tcp.h 服務端聲明文件【1.2】thread_1.h 線程處理聲明文件【1.3】main.cpp 執行源文件【1.4】server_tcp.cpp 服務端邏輯實現源文件【…

cuda 內核啟動

C 使用 __global__ 聲明說明符定義內核&#xff0c;并使用新的 <<<...>>> 執行配置語法指定內核調用的 CUDA 線程數&#xff08;請參閱 C 語言擴展&#xff09;。 每個執行內核的線程都有一個唯一的線程 ID&#xff0c;可以通過內置變量在內核中訪問。 示例…

【最全的excel轉json!!!】使用Python腳本提取excel文本中的數據到json中

比如說&#xff1a;我有一個1.xlsx的文件需要轉成對應的json格式。 1&#xff09; excel 文件的大概內容&#xff1a; 2&#xff09;保存的方式類似于以下這種情況&#xff1a; 用Python腳本來實現 import pandas as pd import json# 讀取Excel文件 excel_path r"D:…

基礎知識篇:大語言模型核心原理解析

1??人工智能基礎概念全景圖 &#x1f4a1; &#x1f9e0;人工智能與機器學習 人工智能&#xff08;AI&#xff09;是計算機科學的一個分支&#xff0c;旨在模擬人類的智能來解決問題。而機器學習&#xff08;ML&#xff09;是AI的一個子集&#xff0c;它的魅力在于不需要顯…