Java实现对doc、pdf、xsl、图片添加水印

1.添加依赖

使用spire.office免费版


<repositories>
            <repository>
            <id>com.e-iceblue</id>
            <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
        </repository>
    </repositories>
   <dependencies>
        <dependency>
            <groupId> e-iceblue </groupId>
            <artifactId>spire.office.free</artifactId>
            <version>5.3.1</version>
        </dependency>
    </dependencies>

2.示例代码

代码参照网络搜索结果,部分地方需要优化:

①是否可以不使用缓存区;

②XLSX 水印位置需要调整

import com.spire.doc.*;
import com.spire.doc.FileFormat;
import com.spire.pdf.*;
import com.spire.pdf.graphics.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.geom.Dimension2D;
import java.awt.image.BufferedImage;
import com.spire.doc.documents.Paragraph;
import com.spire.doc.documents.ShapeLineStyle;
import com.spire.doc.documents.ShapeType;
import com.spire.doc.documents.WatermarkLayout;
import com.spire.doc.fields.ShapeObject;
import com.spire.pdf.graphics.PdfTilingBrush;
import com.spire.xls.ViewMode;
import com.spire.xls.Workbook;
import com.spire.xls.Worksheet;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.*;
import java.security.SecureRandom;
import java.util.Random;


import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.*;


public class WaterMarkUtils {

    /**
     * 缓存区路径
     */
    private static String CACHE_PATH = System.getProperty("user.dir")+"/cache/";

    private static final Logger logger = LoggerFactory.getLogger(WaterMarkUtils.class);


    /**
     * 图片添加文字水印
     * @param logoText 水印文字
     * @param srcFile 原图片文件
     * @param degree 旋转角度
     * @param color 水印文字颜色
     */
    public static MultipartFile setWaterMarkToImageByWords(MultipartFile srcFile, String logoText, Integer degree, Color color) {
        InputStream is = null;
        OutputStream os = null;
        try {
            // 1、源图片
            InputStream inputImg = srcFile.getInputStream();
            Image srcImg = ImageIO.read(inputImg);
            BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), java.awt.Image.SCALE_SMOOTH), 0, 0, null);
            // 4、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree));
            }
            // 5、设置水印文字颜色
            g.setColor(color);
            // 6、设置水印文字Font
            Font font = new Font("宋体", Font.BOLD, 150);
            g.setFont(font);
            // 7、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.45f));
            // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
            JLabel label = new JLabel(logoText);
            FontMetrics metrics = label.getFontMetrics(font);
            int width = metrics.stringWidth(label.getText())+80;//文字水印的宽
            int rowsNumber = buffImg.getWidth()/width;// 图片的高  除以  文字水印的宽    ——> 打印的行数(以文字水印的宽为间隔)
            int columnsNumber = buffImg.getWidth()/width;//图片的宽 除以 文字水印的宽   ——> 每行打印的列数(以文字水印的宽为间隔)
            for(int j=0;j<rowsNumber;j++){
                for(int i=0;i<columnsNumber;i++){
                    g.drawString(logoText, i*width + j*width, -i*width + j*width+120);//画出水印,并设置水印位置
                }
            }
            // 9、释放资源
            g.dispose();

            // 获取图片文件名 xxx.png xxx
            String originFileName = srcFile.getOriginalFilename();
            // 获取原图片后缀 png
            int lastSplit = originFileName.lastIndexOf(".");
            String suffix = originFileName.substring(lastSplit + 1);
            // 获取图片原始信息
            File file = new File(CACHE_PATH + srcFile.getOriginalFilename());
            if (!file.getParentFile().exists()) {
                logger.info("not exists");
                //创建上级目录
                file.getParentFile().mkdir();
            }
            OutputStream bs = new FileOutputStream(CACHE_PATH + srcFile.getOriginalFilename());
            ImageOutputStream imOut = ImageIO.createImageOutputStream(bs);
            ImageIO.write(buffImg, suffix, imOut);
            // 加水印后的文件上传
            srcFile = fileToMultipart(CACHE_PATH + srcFile.getOriginalFilename());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != is)
                    is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (null != os)
                    os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return srcFile;
    }
    //============================================2、PDF添加动态文字水印==================================================

    /**
     * PDF添加文字水印
     * @param srcPdf 上传文件
     * @param logoText 水印文字
     * @param degree 旋转角度
     * @param color 水印文字颜色
     */
    public static MultipartFile  setWaterMarkToPdfByWords(MultipartFile srcPdf, String logoText, Integer degree, Color color) throws IOException {
        try {
            InputStream inputStream = srcPdf.getInputStream();
            PdfDocument pdf = new PdfDocument();
            pdf.loadFromStream(inputStream);
            //加载示例文档
            Font font = new Font("宋体", 24,24);
            PdfTrueTypeFont pdfTrueTypeFont = new PdfTrueTypeFont(font, true);//true防止中文乱码
            for (Object obj  : pdf.getPages()) {
                PdfPageBase page = (PdfPageBase) obj;
                Dimension2D dimension2D = new Dimension();
                dimension2D.setSize(page.getCanvas().getClientSize().getWidth() / 2, page.getCanvas().getClientSize().getHeight() / 3);
                PdfTilingBrush brush = new PdfTilingBrush(dimension2D);
                brush.getGraphics().setTransparency(0.3F);
                brush.getGraphics().save();
                brush.getGraphics().translateTransform((float) brush.getSize().getWidth() / 2, (float) brush.getSize().getHeight() / 2);
                brush.getGraphics().rotateTransform(-45);
                brush.getGraphics().drawString(logoText, pdfTrueTypeFont, PdfBrushes.getViolet(), 0, 0, new PdfStringFormat(PdfTextAlignment.Center));
                brush.getGraphics().restore();
                brush.getGraphics().setTransparency(1);
                Rectangle2D loRect = new Rectangle2D.Float();
                loRect.setFrame(new Point2D.Float(0, 0), page.getCanvas().getClientSize());
                page.getCanvas().drawRectangle(brush, loRect);

            }
          /* pdf.saveToFile(CACHE_PATH + "2.pdf");
            pdf.close();*/
            //保存文档
           File file = new File(CACHE_PATH + srcPdf.getOriginalFilename());
            if (!file.getParentFile().exists()) {
                logger.info("not exists");
                //创建上级目录
                file.getParentFile().mkdir();
            }
            //设置缓存区
            pdf.saveToFile(CACHE_PATH + srcPdf.getOriginalFilename());
            pdf.close();
            //读取缓存区的文件
            srcPdf = fileToMultipart(CACHE_PATH + srcPdf.getOriginalFilename());
        } catch (Exception e) {
            logger.info("pdf添加水印异常: "+e);
            e.printStackTrace();
        }
            return srcPdf;
    }


    //============================================3、DOCX/DOC添加文字水印==================================================
    /**
     * DOCX/DOC添加文字水印
     * @param srcPdf 上传文件
     * @param logoText 水印文字
     * @param degree 旋转角度
     * @param color 水印文字颜色
     */
    public static MultipartFile  setWaterMarkToDocByWords( MultipartFile srcPdf, String logoText, Integer degree, Color color) {
       try{
           InputStream inputStream = srcPdf.getInputStream();
           Document doc = new Document();
           doc.loadFromStream(inputStream, FileFormat.Auto);
           //添加艺术字并设置大小
           ShapeObject shape = new ShapeObject(doc, ShapeType.Text_Plain_Text);
           shape.setWidth(60);
           shape.setHeight(20);
           //设置艺术字文本内容、颜色,位置及样式
           shape.setVerticalPosition(30);
           shape.setHorizontalPosition(20);
           shape.setRotation(315);
           shape.getWordArt().setText(logoText);
           shape.setFillColor(color);
           shape.setLineStyle(ShapeLineStyle.Single);
           shape.setStrokeColor(color);
           //new Color(192, 192, 192, 255)
           shape.setStrokeWeight(1);

           Section section;
           HeaderFooter header;
           for (int n = 0; n < doc.getSections().getCount(); n++) {
               section = doc.getSections().get(n);
               //获取section的页眉
               header = section.getHeadersFooters().getHeader();
               Paragraph paragraph1;
               for (int i = 0; i < 3; i++) {
                   //添加段落到页眉
                   paragraph1 = header.addParagraph();
                   for (int j = 0; j < 3; j++) {
                       //复制艺术字并设置多行多列位置
                       shape = (ShapeObject) shape.deepClone();
                       shape.setVerticalPosition(50 + 150 * i);
                       shape.setHorizontalPosition(20 + 160 * j);
                       paragraph1.getChildObjects().add(shape);
                   }
               }
           }
           //保存文档
           File file = new File(CACHE_PATH + srcPdf.getOriginalFilename());
           if (!file.getParentFile().exists()) {
               logger.info("not exists");
               //创建上级目录
               file.getParentFile().mkdir();
           }
          doc.saveToFile(CACHE_PATH + srcPdf.getOriginalFilename());
           //读取缓存区的文件
           srcPdf = fileToMultipart(CACHE_PATH + srcPdf.getOriginalFilename());

       } catch (Exception e) {
           logger.info("doc添加水印异常: "+e);
           e.printStackTrace();
       }
        return srcPdf;
    }

    /**
     * 读取缓存区的文件
     * @param path 文件路径
     */
    private static MultipartFile fileToMultipart(String path){
        File file = new File(path);
        //无参构造,文件大小最大值便是默认值10kb,超过10Kb便会通过生成临时文件转化不占用内存
        FileItemFactory factory = new DiskFileItemFactory();
        FileItem item = factory.createItem("textField", "text/plain", true, file.getName());
        int bytesRead;
        byte[] buffer = new byte[path.length()];
        try (FileInputStream fis = new FileInputStream(file);
             OutputStream os = item.getOutputStream()) {
            while ((bytesRead = fis.read(buffer, 0, path.length())) != -1) {
                os.write(buffer, 0, bytesRead);
            }
        } catch (IOException e) {
            logger.info("文件转化失败, fileUrl: "+ file.getName());
            logger.info("e: "+e);
            return null;
        }finally {
            //操作完删除缓存区文件
            file.delete();
        }
        return new CommonsMultipartFile(item);
    }

    //============================================4、XLS/XLSL添加文字水印==================================================
    /**
     * XLSX添加文字水印
     * @param srcFile 上传文件
     * @param logoText 水印文字
     * @param degree 旋转角度
     * @param color 水印文字颜色
     */
   public static MultipartFile setWaterMarkToXlsxByWords(MultipartFile srcFile, String logoText, Integer degree, Color color){

       try{
           com.spire.xls.Workbook wb = new com.spire.xls.Workbook();
           InputStream inputStream = srcFile.getInputStream();
           wb.loadFromStream(inputStream);

           //设置文本和字体大小
           Font font = new Font("仿宋", Font.PLAIN, 40);

           for (int i =0;i<wb.getWorksheets().getCount();i++)
           {
               Worksheet sheet = wb.getWorksheets().get(i);
               //调用DrawText() 方法插入图片
               BufferedImage imgWtrmrk = drawText(degree,logoText + "     "+logoText + "     "+ logoText, font, color, Color.white, sheet.getPageSetup().getPageHeight(), sheet.getPageSetup().getPageWidth());
               //将图片设置为页眉
               sheet.getPageSetup().setCenterHeaderImage(imgWtrmrk);
               sheet.getPageSetup().setCenterHeader("&G");

               //将显示模式设置为Layout
               sheet.setViewMode(ViewMode.Layout);
           }
           //保存文档
           File file = new File(CACHE_PATH + srcFile.getOriginalFilename());
           if (!file.getParentFile().exists()) {
               logger.info("not exists");
               //创建上级目录
               file.getParentFile().mkdir();
           }
           wb.saveToFile(CACHE_PATH + srcFile.getOriginalFilename());
           //读取缓存区的文件
           srcFile = fileToMultipart(CACHE_PATH + srcFile.getOriginalFilename());
       }catch (Exception e){
           logger.info("xlsx添加水印异常: "+e);
       }
       return srcFile;
    }

    private static BufferedImage drawText (Integer degree,String text, Font font, Color textColor, Color backColor,double height, double width)
    {
        //定义图片宽度和高度
        BufferedImage img = new BufferedImage((int) width, (int) height, BufferedImage.TYPE_INT_ARGB);

        Graphics2D loGraphic = img.createGraphics();

        //获取文本size
        FontMetrics loFontMetrics = loGraphic.getFontMetrics(font);
        int liStrWidth = loFontMetrics.stringWidth(text);
        int liStrHeight = loFontMetrics.getHeight();

        //文本显示样式及位置        loGraphic.setColor(backColor);
        loGraphic.fillRect(0, 0, (int) width, (int) height);
        loGraphic.translate(((int) width - liStrWidth) / 2, ((int) height - liStrHeight) / 2);
        loGraphic.rotate(Math.toRadians(degree));
        loGraphic.translate(-((int) width - liStrWidth) / 2, -((int) height - liStrHeight) / 2);
        loGraphic.setFont(font);
        loGraphic.setColor(textColor);
        loGraphic.drawString(text, ((int) width - liStrWidth) /6 , ((int) height - liStrHeight) /6);
        loGraphic.drawString(text,((int) width - liStrWidth) /3, ((int) height - liStrHeight) /3);
        loGraphic.drawString(text,((int) width - liStrWidth) /2, ((int) height - liStrHeight) /2);
        loGraphic.dispose();
        return img;
    }

    public static String getCharAndNumr(int length) {

        SecureRandom random = new SecureRandom();

        StringBuffer valSb = new StringBuffer();

        String charStr = "0123456789";

        int charLength = charStr.length();

        for (int i = 0; i < length; i++) {

            int index = random.nextInt(charLength);

            valSb.append(charStr.charAt(index));

        }

        return valSb.toString();

    }
}

参考:https://blog.csdn.net/u011293064/article/details/115730903等


版权声明:本文为m0_71366343原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。