java使用poi对Word插入一个ole对象附件(pdf为例)

关于这个网上资料很少,最后在下面这个代码找到了解决方案

主要实现方式是将docx转为xml后,参考ole对象的xml内容进行生成并插入。原文在最后生成的ole对象双击后图片会变形或者丢失,我将一个docx文档转为xml后参考xml内容做了一部分修改,亲测wps和office都正常

下面是代码实现(用的poi4.2,5.0以上的也能用,修改一些方法的参数类型就行(基本都是一些枚举),具体参考5.0的api)
注:除poi外还需要导入的依赖
implementation ‘org.apache.poi:ooxml-schemas:1.4’
5.0版本以上的,不要用ooxml-schemas,要用
implementation ‘org.apache.poi:poi-ooxml-full:5.3.0’

// 插入文件的主要实现代码 start
final MyRelations oleRelDef = MyRelations.OLE_OBJECT;
intoleNumber = document.getPackage().getUnusedPartIndex(oleRelDef.getDefaultFileName());

POIXMLDocumentPart.RelationPart oleRel = document.createRelationship(oleRelDef, MyFactory.inst, oleNumber, false);
try (OutputStream os = oleRel.getDocumentPart().getPackagePart().getOutputStream();
     POIFSFileSystem poifs = new POIFSFileSystem();) {
    // embeds the contents -> double click and return changes the image to a preview
//                                         embedPDF(poifs, fis);
    // add content via OLE package
    embedPDFasPackage(poifs, fis, UUID.fastUUID() + ".pdf");
    poifs.writeFilesystem(os);
}

// pdf图标的base64字符串,根据自己需求修改
String base64 = "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";
byte[] imageBytes = Base64Decoder.decode(base64);

// 先将Base64转为文件(Hutools提供了便捷方法,这里临时保存到本地磁盘,处理完后可删除该临时文件)
Image bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
// 添加水印(这里以文字水印为例,设置水印文字、字体、颜色、透明度、位置等)
String tmpName = UUID.fastUUID() + ".jpg"; // 图片暂存

int height = 300;
int width = Math.max(40 * attachFile.getName().length(), 256);
create(attachFile.getName(), bufferedImage, tmpName, width, height);
InputStream tmpImgFIS = Files.newInputStream(Paths.get(tmpName));

String imgRel = document.addPictureData(tmpImgFIS, Document.PICTURE_TYPE_JPEG);
addOleShape1(run, imgRel, oleRel.getRelationship().getId(), width, height);

tmpImgFIS.close();
FileUtil.del(tmpName);
}
    /**
     * 生成带标题的图片
     *
     * @param str:
     * @param image:
     * @param newPath:
     * @param width:
     * @param height:
     * @return: void
     */
    public static void create(String str, Image image, String newPath, int width, int height) {
        try {
            File file = new File(newPath);
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2 = bi.createGraphics();
            g2.setBackground(Color.WHITE);
            g2.clearRect(0, 0, width, height);
            g2.drawImage(image, (width - 256) / 2, 0, 256, 256, null); //这里减去25是为了防止字和图重合
            /** 设置生成图片的文字样式 * */
            Font font = new Font("黑体", Font.BOLD, 40);
            g2.setFont(font);
            g2.setPaint(Color.BLACK);
            /** 设置字体在图片中的位置 在这里是居中* */
            FontRenderContext context = g2.getFontRenderContext();
            Rectangle2D bounds = font.getStringBounds(str, context);
            double x = (width - bounds.getWidth()) / 2;
            //double y = (height - bounds.getHeight()) / 2; //Y轴居中
            double y = (height - bounds.getHeight());
            double ascent = -bounds.getY();
            double baseY = y + ascent;
            /** 防止生成的文字带有锯齿 * */
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            /** 在图片上生成文字 * */
            g2.drawString(str, (int) x, (int) baseY);
            ImageIO.write(bi, "jpg", file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建ole对象
     * @param poifs:
     * @param pdfIS:
     * @param pdfName:
     * @return: void
     */
    static void embedPDFasPackage(POIFSFileSystem poifs, InputStream pdfIS, String pdfName) throws IOException {

        Ole10Native ole10Native = new Ole10Native(pdfName, pdfName, pdfName, IoUtil.readBytes(pdfIS));
        poifs.getRoot().setStorageClsid(ClassIDPredefined.OLE_V1_PACKAGE.getClassID());
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ole10Native.writeOut(bos);
        poifs.createDocument(new ByteArrayInputStream(bos.toByteArray()), Ole10Native.OLE10_NATIVE);
    }

    static void addOleShape1(XWPFRun run, String imgRel, String oleRel, int width, int height) {
        int typeCounter = 75;
        int shapeCounter = 1025;

        CTR ctr = run.getCTR();
        CTObject obj = ctr.addNewObject();
        obj.setDxaOrig(BigInteger.valueOf(2190));
        obj.setDyaOrig(BigInteger.valueOf(1440));

        CTGroup grp = CTGroup.Factory.newInstance();
        CTShapetype st = grp.addNewShapetype();
        st.setCoordsize("21600,21600");
        st.setFilled(STTrueFalse.F);
        st.setId("_x0000_t" + typeCounter);
        st.setPreferrelative(com.microsoft.schemas.office.office.STTrueFalse.T);
        st.setPath2("m@4@5l@4@11@9@11@9@5xe");
        st.setStroked(STTrueFalse.F);
        st.setSpt(75);
        st.addNewStroke().setJoinstyle(STStrokeJoinStyle.MITER);

        CTFormulas form = st.addNewFormulas();
        String[] clumsyRect = {
                "if lineDrawn pixelLineWidth 0",
                "sum @0 1 0",
                "sum 0 0 @1",
                "prod @2 1 2",
                "prod @3 21600 pixelWidth",
                "prod @3 21600 pixelHeight",
                "sum @0 0 1",
                "prod @6 1 2",
                "prod @7 21600 pixelWidth",
                "sum @8 21600 0",
                "prod @7 21600 pixelHeight",
                "sum @10 21600 0"
        };
        for (String cr : clumsyRect) {
            form.addNewF().setEqn(cr);
        }

        CTPath path = st.addNewPath();
        path.setGradientshapeok(STTrueFalse.T);
        path.setConnecttype(STConnectType.RECT);
        path.setExtrusionok(com.microsoft.schemas.office.office.STTrueFalse.F);

        CTLock lock = st.addNewLock();
        lock.setAspectratio(com.microsoft.schemas.office.office.STTrueFalse.T);
        lock.setExt(STExt.EDIT);

        CTShape shape = grp.addNewShape();
        shape.setId("_x0000_i" + shapeCounter);
        shape.setStyle("width:" + width / 5 + "pt;height:" + height / 5 + "pt");
        shape.setType("#_x0000_t" + typeCounter);

        CTImageData imgDat = shape.addNewImagedata();
        imgDat.setId2(imgRel);
        imgDat.setTitle("");

        OLEObjectDocument oleParent = OLEObjectDocument.Factory.newInstance();
        CTOLEObject ole = oleParent.addNewOLEObject();
        ole.setDrawAspect(STOLEDrawAspect.ICON);
        ole.setObjectID("_1468075725");
        ole.setProgID("Package");
        ole.setShapeID("_x0000_i" + shapeCounter);
        ole.setType(STOLEType.EMBED);
        ole.setId(oleRel);
        ole.setLockedField(STTrueFalseBlank.T);

        XmlCursor objCur = obj.newCursor();
        objCur.toFirstContentToken();

        XmlCursor grpCur = grp.newCursor();
        grpCur.copyXmlContents(objCur);
        grpCur.dispose();

        XmlCursor oleCur = oleParent.newCursor();
        oleCur.copyXmlContents(objCur);
        oleCur.dispose();
        objCur.dispose();

    }

    static class MyRelations extends POIXMLRelation {

        static final MyRelations OLE_OBJECT = new MyRelations(
                XSLFRelation.OLE_OBJECT.getContentType(),
                XSLFRelation.OLE_OBJECT.getRelation(),
                "/word/embeddings/oleObject#.bin",
                XSLFRelation.OLE_OBJECT.getNoArgConstructor(),
                XSLFRelation.OLE_OBJECT.getPackagePartConstructor(),
                XSLFRelation.OLE_OBJECT.getParentPartConstructor()
        );

        private MyRelations(String type, String rel, String defaultName, POIXMLRelation.NoArgConstructor noArgConstructor, POIXMLRelation.PackagePartConstructor packagePartConstructor, POIXMLRelation.ParentPartConstructor parentPartConstructor) {
            super(type, rel, defaultName, noArgConstructor, packagePartConstructor, parentPartConstructor);
        }
    }

    static class MyFactory extends POIXMLFactory {
        static final MyFactory inst = new MyFactory();

        protected POIXMLRelation getDescriptor(String relationshipType) {
            return MyRelations.OLE_OBJECT;
        }

        protected POIXMLDocumentPart createDocumentPart
                (Class<? extends POIXMLDocumentPart> cls, Class<?>[] classes, Object[] values)
                throws SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
            return new MyObjectData();
        }
    }

    static class MyObjectData extends POIXMLDocumentPart {

        /**
         * Create a new XSLFObjectData node
         */
        MyObjectData() {
        }

        public MyObjectData(final PackagePart part) {
            super(part);
        }

        /**
         * XSLFObjectData objects store the actual content in the part directly without keeping a
         * copy like all others therefore we need to handle them differently.
         */
        @Override
        protected void prepareForCommit() {
            // do not clear the part here
        }


        public void setData(final byte[] data) throws IOException {
            try (final OutputStream os = getPackagePart().getOutputStream()) {
                os.write(data);
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值