java给图片、word、ppt、excel、pdf添加水印

使用poi、itextpdf、imageio等技术

只支持高版本的office,即支持docx、pptx、xlsx

 

给word添加水印遇到的问题:

1、遇到有页眉的word时水印添加失败

2、水印最底层被图片表格覆盖

 

maven配置

<dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>
        <!--2007 docx文件读取,需要导入poi-ooxml-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>3.17</version>
        </dependency>
        <!--2003 doc文件的读取,需要导入poi-scratchpad-->
        <!--<dependency>-->
        <!--<groupId>org.apache.poi</groupId>-->
        <!--<artifactId>poi-scratchpad</artifactId>-->
        <!--<version>3.8</version>-->
        <!--</dependency>-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.0</version>
            <exclusions>
                <!--解决含嵌入文件ppt转换报错 ArrayStoreException-->
                <exclusion>
                    <artifactId>xmlbeans</artifactId>
                    <groupId>org.apache.xmlbeans</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.16</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>
        <!--twelvemonkeys图片处理-->
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-jpeg</artifactId>
            <version>3.6</version>
        </dependency>
        <dependency>
            <groupId>com.twelvemonkeys.imageio</groupId>
            <artifactId>imageio-tiff</artifactId>
            <version>3.6</version>
        </dependency>

        <!--
        Optional dependency. Needed only if you deploy `ImageIO` plugins as part of a web app.
        Make sure you add the `IIOProviderContextListener` to your `web.xml`, see above.
        -->
        <dependency>
            <groupId>com.twelvemonkeys.servlet</groupId>
            <artifactId>servlet</artifactId>
            <version>3.6</version>
        </dependency>

代码工具类

package com.feng.util;

import com.feng.bean.ResultCode;
import com.feng.error.MyException;
import com.itextpdf.text.*;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.Image;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Field;

/**
 * @Author: feng
 * @Date: 2020/9/28 2:35 下午
 */
@Slf4j
public class WaterMarkUtils {

    // 水印透明度
    private static float alpha = 0.5f;
    // 水印之间的间隔
    private static final int XMOVE = 200;
    // 水印之间的间隔
    private static final int YMOVE = 200;

    public static void main(String[] args) {
        addPictureWaterMark("d:/tmp/love.jpg", "d:/tmp/love.png", "我是水印");
        setPictureWatermark("d:/tmp/love.jpg", "d:/tmp/love.png", Color.GRAY, "我是水印");
        setWordWaterMark("d:/tmp/love.docx", "d:/tmp/love1.docx", "我是水印", "docx");
        setPdfWatermark("d:/tmp/love.pdf", "d:/tmp/love1.pdf", "我是水印");
        setExcelWaterMark("d:/tmp/love.xlsx", "d:/tmp/love1.xlsx", "我是水印");
        setPPTWaterMark("d:/tmp/love.pptx", "d:/tmp/love1.pptx", "我是水印");
    }

    /**
     * @param srcImgPath       源图片路径
     * @param tarImgPath       保存的图片路径
     * @param waterMarkContent 水印内容
     */
    public static void addPictureWaterMark(String srcImgPath, String tarImgPath,
                                           String waterMarkContent) {
        FileOutputStream outImgStream = null;
        try {
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);// 得到文件
            Image srcImg = ImageIO.read(srcImgFile);// 文件转化为图片
            int srcImgWidth = srcImg.getWidth(null);// 获取图片的宽
            int srcImgHeight = srcImg.getHeight(null);// 获取图片的高
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight,
                    BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            // 设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            // 设置水印旋转
            g.rotate(Math.toRadians(-40),
                    (double) bufImg.getWidth() / 2,
                    (double) bufImg.getHeight() / 2);
            g.setColor(new Color(107, 109, 106)); // 根据图片的背景设置水印颜色
            Font font = new Font("宋体", Font.PLAIN, 20);
            g.setFont(font); // 设置字体
            // 设置水印文字透明度
//			g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha));

            //根据不同的像素判断多个水印还是单个水印300*300
            if (srcImgWidth > 300 && srcImgHeight > 300) {
                //多个水印
                // 设置水印的坐标
                int x = -srcImgWidth / 2;
                int y = -srcImgHeight / 2;
                int markWidth = font.getSize() * getTextLength(waterMarkContent);// 字体长度
                int markHeight = font.getSize();// 字体高度
                // 循环添加水印
                while (x < srcImgWidth * 1.5) {
                    y = -srcImgHeight / 2;
                    while (y < srcImgHeight * 1.5) {
                        g.drawString(waterMarkContent, x, y);
                        y += markHeight + YMOVE;
                    }
                    x += markWidth + XMOVE;
                }
            } else {
                //单个水印
                int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
                int y = srcImgHeight / 2;
                g.drawString(waterMarkContent, x, y);
            }
            g.dispose();
            // 输出图片
            outImgStream = new FileOutputStream(tarImgPath);
            String formatName = srcImgPath.substring(srcImgPath.lastIndexOf(".") + 1, srcImgPath.length());
            ImageIO.write(bufImg, formatName, outImgStream);
            outImgStream.flush();
        } catch (Exception e) {
            log.error("addPictureWatermark fail", e);
            throw new MyException(ResultCode.FAILURE, "addPictureWatermark fail");
        } finally {
            if (outImgStream != null) {
                try {
                    outImgStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 图片添加水印
     *
     * @param srcImgPath       需要添加水印的图片的路径
     * @param outImgPath       添加水印后图片输出路径
     * @param markContentColor 水印文字的颜色
     * @param waterMarkContent 水印的文字
     */
    public static void setPictureWatermark(String srcImgPath, String outImgPath, Color markContentColor, String waterMarkContent) {
        FileOutputStream outImgStream = null;
        try {
            // 读取原图片信息
            File srcImgFile = new File(srcImgPath);
            Image srcImg = ImageIO.read(srcImgFile);
            int srcImgWidth = srcImg.getWidth(null);
            int srcImgHeight = srcImg.getHeight(null);
            // 加水印
            BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);
            Graphics2D g = bufImg.createGraphics();
            g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);
            Font font = new Font("宋体", Font.BOLD, srcImgHeight / 6);
            //根据图片的背景设置水印颜色
            g.setColor(markContentColor);
            //设置旋转角度
            g.rotate(Math.toRadians(-45), (double) bufImg.getWidth() / 2, (double) bufImg.getHeight() / 2);
            //设置水印透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.2F));

            g.setFont(font);
            int x = (srcImgWidth - getWatermarkLength(waterMarkContent, g)) / 2;
            int y = srcImgHeight / 2;
            g.drawString(waterMarkContent, x, y);
            g.dispose();
            // 输出图片
            outImgStream = new FileOutputStream(outImgPath);
            ImageIO.write(bufImg, "jpg", outImgStream);
            outImgStream.flush();
            outImgStream.close();
        } catch (Exception e) {
            log.error("setPictureWatermark fail", e);
            throw new MyException(ResultCode.FAILURE, "setPictureWatermark fail");
        } finally {
            if (outImgStream != null) {
                try {
                    outImgStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * word文字水印
     *
     * @param inputPath
     * @param outPath
     * @param markStr
     */
    public static void setWordWaterMark(String inputPath, String outPath, String markStr, String fileType) {
        if ("docx".equals(fileType)) {
            File inputFile = new File(inputPath);
            //2003doc 用HWPFDocument  ; 2007doc 用 XWPFDocument
            XWPFDocument doc = null;
            try {
                OPCPackage pack = POIXMLDocument.openPackage(inputPath);
                doc = new XWPFDocument(pack);
//                doc = new XWPFDocument(new FileInputStream(inputFile));
            } catch (FileNotFoundException e) {
                log.error("setWordWaterMark fail: 源文件不存在", e);
                throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 源文件不存在");
            } catch (IOException e) {
                log.error("setWordWaterMark fail: 读取源文件IO异常", e);
                throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 读取源文件IO异常");
            } catch (Exception e) {
                log.error("setWordWaterMark fail: 不支持的文档格式", e);
                throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 不支持的文档格式");
            }
            XWPFParagraph paragraph = doc.createParagraph();
            XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy();
            if (headerFooterPolicy == null) {
                headerFooterPolicy = doc.createHeaderFooterPolicy();
            }
            // create default Watermark - fill color black and not rotated
            headerFooterPolicy.createWatermark(markStr);
            // get the default header
            // Note: createWatermark also sets FIRST and EVEN headers
            // but this code does not updating those other headers
            XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
            paragraph = header.getParagraphArray(0);
//            // get com.microsoft.schemas.vml.CTShape where fill color and rotation is set
//            paragraph.getCTP().newCursor();
//            System.out.println(paragraph.getCTP().getRArray(0));
//            System.out.println(paragraph.getCTP().getRArray(0).getPictArray(0));
            org.apache.xmlbeans.XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
                    new javax.xml.namespace.QName("urn:schemas-microsoft-com:vml", "shape"));
            if (xmlobjects.length > 0) {
                com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape) xmlobjects[0];
                ctshape.setFillcolor("#D3D3D3");
                ctshape.setStyle(ctshape.getStyle() + ";rotation:315" + ";height:60pt;width:360pt");
            }
            File file = new File(outPath);
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    log.error("setWordWaterMark fail: 创建输出文件IO异常", e);
                    throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 创建输出文件失败");
                }
            }
            try {
                doc.write(new FileOutputStream(outPath));
            } catch (FileNotFoundException e) {
                log.error("setWordWaterMark fail: 输出文件不存在", e);
                throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail: 创建输出文件失败");
            } catch (IOException e) {
                log.error("setWordWaterMark fail: ", e);
                throw new MyException(ResultCode.FAILURE, "setWordWaterMark fail");
            } finally {
                if (doc != null) {
                    try {
                        doc.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * pdf设置文字水印
     *
     * @param inputPath
     * @param outPath
     * @param markStr
     */
    public static void setPdfWatermark(String inputPath, String outPath, String markStr) {
        File file = new File(outPath);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                log.error("setPdfWatermark fail: 创建输出文件IO异常", e);
                throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail: 创建输出文件IO异常");
            }
        }
        BufferedOutputStream bufferOut = null;
        try {
            bufferOut = new BufferedOutputStream(new FileOutputStream(file));
        } catch (FileNotFoundException e) {
            log.error("setPdfWatermark fail: 源文件不存在", e);
            throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail: 源文件不存在");
        }
        PdfStamper stamper = null;
        int total = 0;
        PdfContentByte content;
        Rectangle pageSizeWithRotation = null;
        BaseFont base = null;
        PdfReader reader = null;
        try {
            reader = new PdfReader(inputPath);
            //解决PdfReader not opened with owner password
            Field f = PdfReader.class.getDeclaredField("ownerPasswordUsed");
            f.setAccessible(true);
            f.set(reader, Boolean.TRUE);
            stamper = new PdfStamper(reader, bufferOut);
            total = reader.getNumberOfPages() + 1;
            base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
        } catch (IOException e) {
            log.error("setPdfWatermark fail:", e);
            throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
        } catch (DocumentException e) {
            log.error("setPdfWatermark fail:", e);
            throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        // 获取水印文字的高度和宽度
        int textH = 0, textW = 0;
        JLabel label = new JLabel();
        label.setText(markStr);
        FontMetrics metrics = label.getFontMetrics(label.getFont());
        textH = metrics.getHeight();
        textW = metrics.stringWidth(label.getText());
        PdfGState gs = new PdfGState();
        for (int i = 1; i < total; i++) {
            //在内容上方加水印
            content = stamper.getOverContent(i);
            gs.setFillOpacity(0.5f);
            content.saveState();
            content.setGState(gs);
            content.beginText();
//            content.setRGBColorFill(0, 0, 0);
            content.setFontAndSize(base, 20);
            // 获取每一页的高度、宽度
            pageSizeWithRotation = reader.getPageSizeWithRotation(i);
            float pageHeight = pageSizeWithRotation.getHeight();
            float pageWidth = pageSizeWithRotation.getWidth();

            // 根据纸张大小多次添加, 水印文字成30度角倾斜
            for (int height = -5 + textH; height < pageHeight; height = height + YMOVE) {
                for (int width = -5 + textW; width < pageWidth + textW; width = width + XMOVE) {
                    content.showTextAligned(Element.ALIGN_LEFT, markStr, width - textW, height - textH, 30);
                }
            }
            content.endText();
        }
        try {
            stamper.close();
            bufferOut.flush();
            bufferOut.close();
            reader.close();
        } catch (IOException e) {
            log.error("setPdfWatermark fail:", e);
            throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
        } catch (DocumentException e) {
            log.error("setPdfWatermark fail:", e);
            throw new MyException(ResultCode.FAILURE, "setPdfWatermark fail");
        }
    }


    /**
     * excel设置水印
     *
     * @param inputPath
     * @param outPath
     * @param markStr
     */
    public static void setExcelWaterMark(String inputPath, String outPath, String markStr) {
        //读取excel文件
        XSSFWorkbook workbook;
        try {
            workbook = new XSSFWorkbook(new FileInputStream(inputPath));
        } catch (FileNotFoundException e) {
            log.error("setExcelWaterMark fail: 源文件不存在", e);
            throw new MyException(ResultCode.FAILURE, "setExcelWaterMark fail: 源文件不存在");
        } catch (IOException e) {
            log.error("setExcelWaterMark fail: 读取源文件IO异常", e);
            throw new MyException(ResultCode.FAILURE, "setExcelWaterMark fail: 读取源文件IO异常");
        }
        OutputStream fos = null;
        ByteArrayOutputStream os = null;
        try {
            //获取水印
            os = getImage(markStr);
            int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表
                XSSFSheet sheet1 = workbook.getSheetAt(i);
                String rID = sheet1.addRelation(null, XSSFRelation.IMAGES, workbook.getAllPictures().get(pictureIdx)).getRelationship().getId();
                //set background picture to sheet
                sheet1.getCTWorksheet().addNewPicture().setId(rID);
            }
            // Excel文件生成后存储的位置。
            File file = new File(outPath);
            fos = new FileOutputStream(file);
            workbook.write(fos);
        } catch (Exception e) {
            log.error("setExcelWaterMark fail: 创建输出文件IO异常", e);
            throw new MyException(ResultCode.FAILURE, "setExcelWaterMark fail: 创建输出文件IO异常");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * PPT设置水印
     *
     * @param path
     * @param targetpath
     * @param markStr
     * @throws IOException
     */
    public static void setPPTWaterMark(String path, String targetpath, String markStr) {
        XMLSlideShow slideShow;
        try {
            slideShow = new XMLSlideShow(new FileInputStream(path));
        } catch (IOException e) {
            log.error("setPPTWaterMark fail:", e);
            throw new MyException(ResultCode.FAILURE, "setPPTWaterMark fail:获取PPT文件失败");
        }
        ByteArrayOutputStream os = null;
        FileOutputStream out = null;
        try {
            //获取水印
            os = getImage(markStr);
            PictureData pictureData1 = slideShow.addPicture(os.toByteArray(), PictureType.PNG);
            for (XSLFSlide slide : slideShow.getSlides()) {
                XSLFPictureShape pictureShape = slide.createPicture(pictureData1);
//                pictureShape.setAnchor(new java.awt.Rectangle(250, 0, 500, 500));
                pictureShape.setAnchor(pictureShape.getAnchor());
            }
            out = new FileOutputStream(targetpath);
            slideShow.write(out);
        } catch (IOException e) {
            log.error("setPPTWaterMark fail:" + e);
            throw new MyException(ResultCode.FAILURE, "setPPTWaterMark fail:生成ppt文件失败");
        } finally {
            if (slideShow != null) {
                try {
                    slideShow.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 获取水印文字总长度
     *
     * @param waterMarkContent 水印的文字
     * @param g
     * @return 水印文字总长度
     */
    public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
        return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
    }

    /**
     * 获取文本长度。汉字为1:1,英文和数字为2:1
     */
    private static int getTextLength(String text) {
        int length = text.length();
        for (int i = 0; i < text.length(); i++) {
            String s = String.valueOf(text.charAt(i));
            if (s.getBytes().length > 1) {
                length++;
            }
        }
        length = length % 2 == 0 ? length / 2 : length / 2 + 1;
        return length;
    }

    /**
     * 获取水印文字图片流
     *
     * @param text
     * @return
     */
    private static ByteArrayOutputStream getImage(String text) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            // 导出到字节流B
            BufferedImage image = createWaterMarkImageBig(text);
            ImageIO.write(image, "png", os);
        } catch (IOException e) {
            log.error("getImage fail: 创建水印图片IO异常", e);
            throw new MyException(ResultCode.FAILURE, "getImage fail: 创建水印图片IO异常");
        }
        return os;
    }

    /**
     * 根据文字生成水印图片(大号 平铺)
     *
     * @param text
     * @return
     */
    public static BufferedImage createWaterMarkImageBig(String text) {
        Integer width = 1000;
        Integer height = 800;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象
        Font font = new Font("宋体", Font.PLAIN, 70);
        Graphics2D g2d = image.createGraphics();
        image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g2d.dispose();
        g2d = image.createGraphics();
        //设置字体颜色和透明度
        g2d.setColor(new Color(0, 0, 0, 60));
        //设置字体
        g2d.setStroke(new BasicStroke(1));
        //设置字体类型  加粗 大小
        g2d.setFont(font);
        //设置倾斜度
        g2d.rotate(Math.toRadians(-30), (double) image.getWidth() / 2, (double) image.getHeight() / 2);
        FontRenderContext context = g2d.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(text, context);
        double x = (width - bounds.getWidth()) / 2;
        double y = (height - bounds.getHeight()) / 2;
        double ascent = -bounds.getY();
        double baseY = y + ascent;
        //写入水印文字原定高度过小,所以累计写水印,增加高度
        g2d.drawString(text, (int) x, (int) baseY);
        //设置透明度
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        //释放对象
        g2d.dispose();
        return image;
    }
}

 问题:

1、要添加字体到/usr/share/fonts下

2、pptx文件中含有嵌入文件,即在ppt中插入外部文件会异常:

java.lang.ArrayStoreException: null
        at java.lang.System.arraycopy(Native Method)
        at org.apache.xmlbeans.impl.values.XmlObjectBase._typedArray(XmlObjectBase.java:409)
        at org.apache.xmlbeans.impl.values.XmlObjectBase.selectPath(XmlObjectBase.java:457)
        at org.apache.xmlbeans.impl.values.XmlObjectBase.selectPath(XmlObjectBase.java:415)
        at org.apache.poi.xslf.usermodel.XSLFDrawing.<init>(XSLFDrawing.java:44)
        at org.apache.poi.xslf.usermodel.XSLFSheet.initDrawingAndShapes(XSLFSheet.java:201)
        at org.apache.poi.xslf.usermodel.XSLFSheet.getDrawing(XSLFSheet.java:177)
        at org.apache.poi.xslf.usermodel.XSLFSheet.createPicture(XSLFSheet.java:260)

原因是:其他pom引入中含有xmlbeans2.3版本。

解决办法:排除xmlbeans2.3,确保xmlbeans版本是2.6 。