用docx4j向word文档插入图片(用生成的条形码),含正文及页脚

package com.barcode.util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Random;

import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.finders.RangeFinder;
import org.docx4j.jaxb.Context;
import org.docx4j.model.structure.SectionWrapper;
import org.docx4j.openpackaging.exceptions.InvalidFormatException;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.openpackaging.parts.WordprocessingML.FooterPart;
import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart;
import org.docx4j.org.apache.poi.util.IOUtils;
import org.docx4j.relationships.Relationship;
import org.docx4j.wml.Body;
import org.docx4j.wml.CTBookmark;
import org.docx4j.wml.Document;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.FooterReference;
import org.docx4j.wml.HdrFtrRef;
import org.docx4j.wml.Jc;
import org.docx4j.wml.JcEnumeration;
import org.docx4j.wml.ObjectFactory;
import org.docx4j.wml.P;
import org.docx4j.wml.PPr;
import org.docx4j.wml.R;
import org.docx4j.wml.SectPr;
import org.jbarcode.JBarcode;
import org.jbarcode.encode.CodabarEncoder;
import org.jbarcode.paint.BaseLineTextPainter;
import org.jbarcode.paint.WideRatioCodedPainter;
import org.jbarcode.util.ImageUtil;

import com.tg.dc.client.util.FileOprtUtil;

public class BarcodeUtil {

    private static final ObjectFactory factory = Context.getWmlObjectFactory();

    /**
     * Method Description:生成条形码
     *
     * @param templatePath
     *            word文档模板(路径 + 文件名)
     * @param bookmarkName
     *            书签名
     * @return 条形码
     */
    public String insertBarcode(String templatePath, String bookmarkName) {

        String inputCode = ""; // 13位条形码随机数
        Properties prop = new Properties();
        try {

            String barcodePath = ""; // 条形码临时生成存放路径

            // 读取属性文件
            InputStream in = getClass().getResourceAsStream(
                    "barcode.properties");
            prop.load(in); // /加载属性列表
            Iterator<String> it = prop.stringPropertyNames().iterator();
            while (it.hasNext()) {
                String key = it.next();
                if ("barcodePath".equals(key)) {
                    barcodePath = prop.getProperty(key);
                }
            }
            if (in != null) {
                in.close();
            }

            // 删除上次生成的临时文件
            FileOprtUtil fileOprtUtil = new FileOprtUtil();
            fileOprtUtil.deleteFileAndDirectory(barcodePath);

            // 生成13位随机数
            Random random = new Random();
            inputCode += random.nextInt(9) + 1;
            for (int i = 0; i < 12; i++) {
                inputCode += random.nextInt(10);
            }

            this.insertPicture(templatePath, templatePath, bookmarkName,
                    this.getImageFullpath(inputCode, barcodePath));

        } catch (Exception e) {
            System.out.println("条形码插入word文档失败!");
            System.out.println(e);
        }

        return inputCode;
    }

    /**
     * Method Description:生成条形码
     *
     * @param inputCode
     *            条形码串
     * @param barcodePath
     *            条形码存放路径
     * @return 全路径(路径 + 文件名)
     */
    private String getImageFullpath(String inputCode, String barcodePath) {

        String fileName = "";

        // 文件保存位置
        File saveDir = new File(barcodePath);
        if (!saveDir.exists()) {
            saveDir.mkdir();
        }

        try {
            JBarcode localJBarcode = new JBarcode(CodabarEncoder.getInstance(),
                    WideRatioCodedPainter.getInstance(),
                    BaseLineTextPainter.getInstance());
            BufferedImage localBufferedImage = localJBarcode
                    .createBarcode(inputCode);

            fileName = inputCode + ".png";

            this.saveToPNG(barcodePath, localBufferedImage, fileName);

        } catch (Exception localException) {
            localException.printStackTrace();
        }
        return barcodePath + fileName;
    }

    /**
     * Method Description:保存条形码到图片的png格式
     *
     * @param barcodePath
     *            条形码存放路径
     * @param paramBufferedImage
     *            BufferedImage对象
     * @param paramString
     *            条形码串
     */
    private void saveToPNG(String barcodePath,
            BufferedImage paramBufferedImage, String paramString) {
        this.saveToFile(barcodePath, paramBufferedImage, paramString, "png");
    }

    /**
     * Method Description:保存图片到文件夹
     *
     * @param barcodePath
     *            条形码存放路径
     * @param paramBufferedImage
     *            BufferedImage对象
     * @param paramString1
     *            条形码串
     * @param paramString2
     *            图片类型
     */
    private void saveToFile(String barcodePath,
            BufferedImage paramBufferedImage, String paramString1,
            String paramString2) {
        try {
            FileOutputStream localFileOutputStream = new FileOutputStream(
                    barcodePath + paramString1);
            ImageUtil.encodeAndWrite(paramBufferedImage, paramString2,
                    localFileOutputStream, 84, 32);
            if (localFileOutputStream != null) {
                localFileOutputStream.flush();
                localFileOutputStream.close();
            }

        } catch (Exception localException) {
            localException.printStackTrace();
        }
    }

    /**
     * 创建页脚
     *
     * @param wPackage
     * @return
     * @throws Exception
     */
    private FooterPart createFooter(WordprocessingMLPackage wPackage)
            throws Exception {
        FooterPart footerPart = new FooterPart();
        Relationship rel = wPackage.getMainDocumentPart().addTargetPart(
                footerPart);
        this.createFooterReference(wPackage, rel);
        return footerPart;
    }

    /**
     * 创建页脚引用关系
     *
     * @param wPackage
     * @param relationship
     * @throws InvalidFormatException
     */
    private void createFooterReference(WordprocessingMLPackage wPackage,
            Relationship relationship) throws InvalidFormatException {
        List<SectionWrapper> sections = wPackage.getDocumentModel()
                .getSections();

        SectPr sectPr = sections.get(sections.size() - 1).getSectPr();
        // There is always a section wrapper, but it might not contain a sectPr
        if (sectPr == null) {
            sectPr = factory.createSectPr();
            wPackage.getMainDocumentPart().addObject(sectPr);
            sections.get(sections.size() - 1).setSectPr(sectPr);
        }
        FooterReference footerReference = factory.createFooterReference();
        footerReference.setId(relationship.getId());
        footerReference.setType(HdrFtrRef.DEFAULT);
        sectPr.getEGHdrFtrReferences().add(footerReference);
    }

    /**
     * 创建包含图片的内容
     *
     * @param word
     * @param sourcePart
     * @param imageFilePath
     * @return
     * @throws Exception
     */
    public static P newImage(WordprocessingMLPackage word, Part sourcePart,
            String imageFilePath) throws Exception {
        BinaryPartAbstractImage imagePart = BinaryPartAbstractImage
                .createImagePart(word, sourcePart, new File(imageFilePath));

        Inline inline = imagePart.createImageInline(null, null, 0, 0, false,
                1200);
        Drawing drawing = factory.createDrawing();
        drawing.getAnchorOrInline().add(inline);

        R r = factory.createR();
        r.getContent().add(drawing);

        P p = factory.createP();

        PPr pPr = new PPr();
        Jc jc = new Jc();
        // 单元格居中对齐
        jc.setVal(JcEnumeration.CENTER);
        pPr.setJc(jc);
        p.setPPr(pPr);

        p.getContent().add(r);

        return p;
    }

    /**
     * Method Description:使用docx4j插入图片
     *
     * @param templatePath
     *            模板文件路径
     * @param targetPath
     *            生成的文件路径
     * @param bookmarkName
     *            书签名
     * @param imagePath
     *            图片路径
     * @throws Exception
     */
    private void insertPicture(String templatePath, String targetPath,
            String bookmarkName, String imagePath) throws Exception {

        InputStream templateFileIs = new FileInputStream(templatePath);
        // 载入模板文件
        WordprocessingMLPackage wPackage = WordprocessingMLPackage
                .load(templateFileIs);
        /*
         // 提取正文
        MainDocumentPart mainDocumentPart = wPackage.getMainDocumentPart();
        Document wmlDoc = (Document) mainDocumentPart.getJaxbElement();
        Body body = wmlDoc.getBody();
        // 提取正文中所有段落
        List<Object> paragraphs = body.getContent();
        // 提取书签并创建书签的游标
        RangeFinder rt = new RangeFinder("CTBookmark", "CTMarkupRange");
        new TraversalUtil(paragraphs, rt);
        // 遍历书签
        for (CTBookmark bm : rt.getStarts()) {
            // 这儿可以对单个书签进行操作,也可以用一个map对所有的书签进行处理
            if (bm.getName().startsWith(bookmarkName)) {
                // 读入图片并转化为字节数组,因为docx4j只能字节数组的方式插入图片
                InputStream is = new FileInputStream(imagePath);
                byte[] bytes = IOUtils.toByteArray(is);
                // 创建一个行内图片
                BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(wPackage, bytes);
                // createImageInline函数的前四个参数我都没有找到具体啥意思
                // 最有一个是限制图片的宽度,缩放的依据
                Inline inline = imagePart.createImageInline(null, null, 0, 1, false, 2400);
                // 获取该书签的父级段落
                P p = (P) (bm.getParent());
                ObjectFactory factory = new ObjectFactory();
                // R对象是匿名的复杂类型,然而我并不知道具体啥意思,估计这个要好好去看看ooxml才知道
                R run = factory.createR();
                // drawing理解为画布
                Drawing drawing = factory.createDrawing();
                drawing.getAnchorOrInline().add(inline);
                run.getContent().add(drawing);
                p.getContent().add(run);
            }
        }
         */

        // 创建页脚
        FooterPart footerPart = createFooter(wPackage);
        // //添加图片
        footerPart.getContent().add(newImage(wPackage, footerPart, imagePath));

        OutputStream os = new FileOutputStream(targetPath);
        wPackage.save(os);

        if (os != null) {
            os.close();
        }

        if (templateFileIs != null) {
            templateFileIs.close();
        }
    }

}
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
docx4j可以帮助你读取Word文档中的图片和文本内容。下面是一个简单的示例代码,可以读取Word文档中的所有图片和文本,并将它们打印到控制台上: ```java import org.docx4j.Docx4J; import org.docx4j.openpackaging.packages.WordprocessingMLPackage; import org.docx4j.wml.*; import java.io.File; import java.util.List; public class ReadWord { public static void main(String[] args) throws Exception { // 读取Word文档 WordprocessingMLPackage wordMLPackage = Docx4J.load(new File("test.docx")); // 获取文档中的所有段落 List<P> paragraphs = wordMLPackage.getMainDocumentPart().getContent().stream() .filter(obj -> obj instanceof P) .map(obj -> (P) obj) .toList(); // 打印文本内容 for (P paragraph : paragraphs) { List<Object> runs = paragraph.getContent(); for (Object run : runs) { if (run instanceof Text) { System.out.println(((Text) run).getValue()); } } } // 获取文档中的所有图片 List<Object> images = wordMLPackage.getAllElementsFromObjectList( wordMLPackage.getMainDocumentPart(), Drawing.class); // 打印图片信息 for (Object image : images) { if (image instanceof Drawing) { Drawing drawing = (Drawing) image; List<Object> imageRuns = drawing.getAnchorOrInline(); for (Object imageRun : imageRuns) { if (imageRun instanceof Inline) { Inline inline = (Inline) imageRun; List<Object> inlineItems = inline.getGraphic().getGraphicData().getAny(); for (Object inlineItem : inlineItems) { if (inlineItem instanceof org.docx4j.dml.wordprocessingDrawing.Inline) { org.docx4j.dml.wordprocessingDrawing.Inline picture = (org.docx4j.dml.wordprocessingDrawing.Inline) inlineItem; String imageId = picture.getDocPr().getId(); System.out.println("Image ID: " + imageId); // 获取图片二进制数据 byte[] imageData = wordMLPackage.getMainDocumentPart(). getBinaryData(imageId); // 处理图片数据 } } } } } } } } ``` 这个例子中,我们使用了docx4jDocx4J.load()方法来加载Word文档。然后,我们使用getMainDocumentPart()方法获取文档的主体部分,并使用getContent()方法获取文档中的所有内容。我们过滤出所有的段落,并依次打印出文本内容。之后,我们使用getAllElementsFromObjectList()方法获取文档中的所有图片,并使用getBinaryData()方法获取图片的二进制数据。最后,我们可以处理这些图片数据,例如将它们保存到本地磁盘或者上传到服务器。 需要注意的是,这个例子只是一个简单的示例,实际应用中可能需要考虑更多的情况。比如,文档中可能会有多个图片,我们需要使用循环逐一处理。另外,对于大型文档,可能需要考虑使用分页加载等技术来提高性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值