相信很多小伙伴们在做导出pdf或者excel文件时会被要求在文件上加上水印,本篇博客就来讲讲如何为pdf和excel加水印。

导出pdf加水印

其实在导出pdf时加上水印并不难,因为itext提供了添加水印的方法,而且能设置水印的位置角度等等,直接来看一下代码



public void createPDF(String filename) throws IOException {
    Document document = new Document(PageSize.A4);
    try {
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
        document.addTitle("example of PDF");
        document.open();
        PdfPTable table = createTable(writer);  
        document.add(table);
        // 加入水印 
        PdfContentByte waterMar = writer.getDirectContentUnder(); 
        // 开始设置水印 
        waterMar.beginText(); 
        // 设置水印透明度 
        PdfGState gs = new PdfGState(); 
        // 设置填充字体不透明度为0.2f 
        gs.setFillOpacity(0.2f);      
        // 设置水印字体参数及大小 (这里在上一篇博客中已经讲过了) 
        BaseFont baseFont = BaseFont.createFont(JavaPdfHelloWorld.class.getResource("/simsun.ttf").getPath(), BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
        waterMar.setFontAndSize(baseFont,30); 
        // 设置透明度 
        waterMar.setGState(gs); 
        // 设置水印对齐方式 水印内容 X坐标 Y坐标 旋转角度
        waterMar.showTextAligned(Element.ALIGN_RIGHT, "我是水印" , 350, 730, 45);     
        //结束设置 
        waterMar.endText(); 
        waterMar.stroke();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (DocumentException e) {
        e.printStackTrace();
    } finally {
        document.close();
    }
}



Java office生成印章水印 java生成文件excel打水印_java

createTable()方法的代码就不贴了,就是生成一个pdf表格,这在之前的博客中已经提过了。

导出excel加水印

接下来我们着重看一下excel文件怎么加水印,现在业界对excel文件读写大多采用poi这个东西,而poi没有提供添加水印的方法,所以要怎么办呢,我在网上搜索了好久也没找到能直接拿来用的办法,但是看到有人提供思路,先准备一份打了水印的模版Excel,然后加载该模版,再将内容输出到该模版中,以达到为Excel添加水印的目的。这个思路看起来的确可行,然后就开干了,先看代码



public class ExcelUtilTest{
  public void createExcel(HttpServletResponse response)throws Exception {
    //获取excel文件
    File finalXlsxFile = new File("src/main/resources/watermark.xlsx");
    //获取excel文件流
    FileInputStream inputStream = new FileInputStream(finalXlsxFile);
    //根据文件流创建XSSFWorkbook对象
    XSSFWorkbook wb = new XSSFWorkbook(inputStream); 
    XSSFSheet sheet = wb.getSheetAt(0);
    sheet.setDefaultColumnWidth(16);//设置默认列宽
    sheet.setDefaultRowHeightInPoints(20);//设置默认行高
    for(int j = 0;j < 5;j++) {
    XSSFRow row = sheet.createRow(j); 
    for(int i = 0;i<5;i++) {
    XSSFCell cell=row.createCell(i);
    cell.setCellValue("第"+j+"行第"+i+"列");
      }
    }
    //输出Excel文件
    OutputStream output= response.getOutputStream();
    response.reset();
    String  fileName = "水印测试文件";
    response.setHeader("Content-Disposition",
      "attachment; filename=" +new String(fileName.getBytes("UTF-8"), "iso-8859-1")+".xlsx");
    response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); 
    wb.write(output);
    output.close();
  }
}



这个代码换一下文件地址可以直接拿来用,值得注意的是这是用springboot以附件形式导出的,不是用java程序生成的,也就是说我还有一个controller文件,只是没贴出来。

和我们直接生成excel文件代码有所不同的是下面两句代码,如果是直接生成excel文件这构造方法参数是空的,然后getSheetAt()方法改为createSheet()方法即可



XSSFWorkbook wb = new XSSFWorkbook(inputStream); 
XSSFSheet sheet = wb.getSheetAt(0);



至于如何设计excel文件上的水印这个网上教程很多,随便找一个来看就行,我就不赘述了,看一下效果如何

Java office生成印章水印 java生成文件excel打水印_模版_02

这是原始excel

 

Java office生成印章水印 java生成文件excel打水印_模版_03

这是生成后的excel

如果要将其打包部署的话,不能直接根据文件来获取inputStream,需要将代码改一改,将最上面两句代码改成springboot提供的获取类路径下文件流的方法,然后文件文件要放在类路径下。当然,这个在打包所有需要通过文件路径来获取文件的springboot项目情况都适用。



InputStream finalXlsxFile = new ClassPathResource("watermark.xlsx").getInputStream();



总结

相对pdf生成水印的方法,excel这个方法还是有很多不足之处的,比如生成水印的位置不能通过代码更改,如果有多个sheet不能全都加上去(除非事先知道有几个sheet),生成后的excel中的水印可以随意拖动位置(这个貌似可以改进)。总之这份代码是非常简陋的,只能解决最简单的为导出excel文件加水印的需求。