java实现导出excel添加水印或excel转pdf并添加水印

1.通过Map对象存入excel模板中获得excel表,并添加水印

import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public static void exportExcelWatermark(TemplateExportParams templatePath, Map<String, Object> map, String fileName, String markText, HttpServletResponse response){
XSSFWorkbook workbook = (XSSFWorkbook) ExcelExportUtil.exportExcel(templatePath, map);
        ExcelMark.Watermark watermark = new ExcelMark.Watermark();
        //设置水印文字
        watermark.setText(markText);
        BufferedImage image = ExcelMark.createWatermarkImage(watermark);
        // 导出到字节流byte
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        ImageIO.write(image, "png", os);
        int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
        POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);
        XSSFSheet sheet = workbook.getSheetAt(0);
        PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
        String relType = XSSFRelation.IMAGES.getRelation();
        //add relation from sheet to the picture data
        PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
        //set background picture to sheet
        sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
        downLoadExcel(fileName, response, workbook);
}

/**
 * excel下载
 *
 * @param fileName 下载时的文件名称
 * @param response
 * @param workbook excel数据
 */
private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) throws IOException {
        try {
            response.setCharacterEncoding("UTF-8");
            response.setHeader("content-Type", "application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
            workbook.write(response.getOutputStream());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }
/**
 *添加水印方法
 */
@Data
public static class Watermark {
    private Boolean enable;
    private String text;
    private String dateFormat;
    private String color;
}
public static BufferedImage createWatermarkImage(Watermark watermark) {
        if (watermark == null) {
            watermark = new ExcelMark.Watermark();
            watermark.setEnable(true);
//            watermark.setText("userName");
            watermark.setText("水印水印水印");
            watermark.setColor("#C5CBCF");
            watermark.setDateFormat("yyyy-MM-dd HH:mm");
        } else {
            if (StringUtils.isEmpty(watermark.getDateFormat())) {
                watermark.setDateFormat("yyyy-MM-dd HH:mm");
            } else if (watermark.getDateFormat().length() == 16) {
                watermark.setDateFormat("yyyy-MM-dd HH:mm");
            } else if (watermark.getDateFormat().length() == 10) {
                watermark.setDateFormat("yyyy-MM-dd");
            }
            if (StringUtils.isEmpty(watermark.getText())) {
                watermark.setText("水印水印水印");
            }
            if (StringUtils.isEmpty(watermark.getColor())) {
                watermark.setColor("#C5CBCF");
            }
        }
        String[] textArray = watermark.getText().split("\n");
        Font font = new Font("microsoft-yahei", Font.PLAIN, 20);
        Integer width = 500;
        Integer height = 200;

        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 背景透明 开始
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g.dispose();
        // 背景透明 结束
        g = image.createGraphics();
        g.setColor(new Color(Integer.parseInt(watermark.getColor().substring(1), 16)));// 设定画笔颜色
        g.setFont(font);// 设置画笔字体
        g.shear(0.1, -0.26);// 设定倾斜度

//        设置字体平滑
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        int y = 100;
        for (int i = 0; i < textArray.length; i++) {
            g.drawString(textArray[i], 0, y);// 画出字符串
            y = y + font.getSize();
        }
        g.drawString(DateUtils.dateTimeNow(watermark.getDateFormat()), 0, y);// 画出字符串

        g.dispose();// 释放画笔
        return image;

    }

2.将excel转pdf并添加水印(先给excel添加水印会导致导出为pdf后消失)

在pom.xml中引入

    <dependency>
        <groupId>e-iceblue</groupId>
        <artifactId>spire.xls.free</artifactId>
        <version>2.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.4.3</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext-asian</artifactId>
        <version>5.2.0</version>
    </dependency>
public static void exportExcelWatermark(TemplateExportParams templatePath, Map<String, Object> map, String fileName, String markText, HttpServletResponse response) throws Exception {
        XSSFWorkbook workbook = (XSSFWorkbook) ExcelExportUtil.exportExcel(templatePath, map);
        File tempFile = File.createTempFile(fileName, ".xlsx");
        try (FileOutputStream out = new FileOutputStream(tempFile)) {
            workbook.write(out);
        }
        //加载Excel工作表
        com.spire.xls.Workbook wb = new com.spire.xls.Workbook();
        wb.loadFromFile(tempFile.getAbsolutePath());
        Worksheet excelSheet = wb.getWorksheets().get(0);
        File tempPdfFile = File.createTempFile(fileName, ".pdf");
        wb.getConverterSetting().setSheetFitToPage(true);
        excelSheet.saveToPdf(tempPdfFile.getAbsolutePath());
        // 添加水印
        setPdfWaterMarForFileTest(tempPdfFile.getAbsolutePath(),fileName, markText, response);
        // 步骤 7: 清理临时文件
        tempPdfFile.delete();
    }

public static void setPdfWaterMarForFileTest(String inputFile, String fileName, String waterText, HttpServletResponse response) throws Exception {
        // 创建PdfReader对象读取原始PDF文件
        PdfReader reader = new PdfReader(inputFile);

        // 使用 ByteArrayOutputStream 来避免创建临时文件
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            PdfStamper stamper = new PdfStamper(reader, byteArrayOutputStream);
            PdfContentByte waterMar;
            //试了很多字体,这个是itextpdf自带的支持中文的字体
            BaseFont base = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

            PdfGState gs = new PdfGState();
            gs.setFillOpacity(0.3f);
            gs.setStrokeOpacity(0.3f);

            int n = reader.getNumberOfPages();

            for (int i = 1; i <= n; i++) {
                waterMar = stamper.getOverContent(i);
                waterMar.setGState(gs);
                waterMar.setFontAndSize(base, 12);

                com.itextpdf.text.Rectangle pageSizeWithRotation = reader.getPageSizeWithRotation(i);
                float height = pageSizeWithRotation.getHeight();
                float width = pageSizeWithRotation.getWidth();

                String[] marTextArray = stringToStringArray(waterText, 15);
                waterMar.beginText();
                //打印的行数和列数可自行修改
                //135为横向偏移量,可以自行修改
                for (int y = 0; y < 8; y++) {
                    for (int x = 0; x < 7; x++) {
                        for (int t = 0; t < marTextArray.length; t++) {
                            float xFloat = x * 190 + 135 + t * 10;
                            float yFloat = y * 100 + 87 - t * 10;
                            waterMar.showTextAligned(Element.ALIGN_CENTER, marTextArray[t], xFloat, yFloat, 30);
                        }
                    }
                }
                waterMar.endText();
            }

            stamper.close();
            reader.close();

            // 设置响应头以便下载 PDF
            response.reset();
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName+".pdf", "UTF-8"));

            // 将生成的 PDF 写入响应输出流
            try (OutputStream out = response.getOutputStream()) {
                byteArrayOutputStream.writeTo(out);
                out.flush();
            }
        } catch (Exception e) {
            throw new RuntimeException("pdf生成水印失败"); // 可以根据需求进行异常处理
        }
    }

    public static String[] stringToStringArray(String text, int length) {
        //检查参数是否合法
        if (StringUtils.isEmpty(text)) {
            return null;
        }
        if (length <= 0) {
            return null;
        }
        // 首尾空格去除
        text = text.trim();
        //获取整个字符串可以被切割成字符子串的个数
        int n = (text.length() + length - 1) / length;
        String[] splitArr = new String[n];
        for (int i = 0; i < n; i++) {
            if (i < (n - 1)) {
                splitArr[i] = text.substring(i * length, (i + 1) * length);
            } else {
                splitArr[i] = text.substring(i * length);
            }
        }
        return splitArr;
    }
posted @ 2024-09-29 16:37  山茶花llia  阅读(403)  评论(0编辑  收藏  举报