使用poi,pageOffice合并word操作。主要区别在于

  1. poi可以进行后台操作,通过各种各样APi接口,直接进行文件io读写操作,,可用于后台操作,pageoffice需要前端预览后保存(根据封装列子,源码修改另行解决)。
  2. poi对于docx和doc文件兼容不好,提供两套不同api。pageOffice已经封装两类文件。dox转docx本文不做介绍

代码详述

1、poi进行合并

  1. maven引入poi架包
  2. poi文档API
 <!-- word 操作-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-scratchpad</artifactId>
            <version>4.1.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.xmlbeans/xmlbeans -->
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>3.1.0</version>
        </dependency>

*警告:*部门maven集成时,因为XmlBean架包重读,POi运行报错。自行删除xmlBean架包,使用Poi引入的xmlBean

工具类代码

工具类:

1.ByteArrayInputStream() 获取byte[] 字节流文件
2.wordMergeRetPath() 传入文件地址,生成文件

原理:使用 XWPFDocument.getDocument().getBody().xmlText() 获取xml文件信息。对docx的xml文件操作,拼接头尾数据,加入待拼接doxc的xml数据

package io.fileType.word;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPictureData;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBody;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDocument1;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTMarkupRange;

import java.io.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: lixiao
 * Created Date: 2020/7/3 9:06
 * <p>
 * 使用pio处理word
 */
public class WordPoiUtil {
    public volatile int bookMarkCount = 0;

    public static String path = null;


    /**
     * 默认文件生成地址
     * @return
     */
    public String localPath() {
        String localPath = this.getClass().getResource("/").getPath() + "wordEdit" + File.separator;
        File file = new File(localPath);
        if (!file.exists()) {
            file.mkdir();
        }
        this.path = localPath;
        return path;
    }

    public WordPoiUtil() {
        localPath();
    }

    /**
     * 根据传入文件,返回IO流
     * @param inputStreams
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     * @throws XmlException
     */
    public ByteArrayInputStream wordMergeRetIO(List<InputStream> inputStreams) throws IOException, InvalidFormatException, XmlException {
        return wordMerge(inputStreams);
    }

    /**
     * 根据传入文件集合、地址、文件名称生成文件,返回文件全路径
     * @param inputStreams
     * @param path
     * @param fileName
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     * @throws XmlException
     */
    public String wordMergeRetPath(List<InputStream> inputStreams, String path, String fileName) throws IOException, InvalidFormatException, XmlException {
        if (path == null || path == "") {
            path = this.path;
        }
        if (fileName == null || fileName == "") {
            fileName = String.valueOf(System.currentTimeMillis()) + String.valueOf((int) Math.random() * 1000) + ".docx";
        }
        String fileFullPath = path + fileName;
        ByteArrayInputStream byteArrayInputStream = wordMerge(inputStreams);
        OutputStream outputStream = new FileOutputStream(new File(fileFullPath));
        int count = byteArrayInputStream.available();
        byte[] bytes = new byte[count];
        byteArrayInputStream.read(bytes, 0, count);
        outputStream.write(bytes);
        outputStream.close();
        return fileFullPath;
    }


    /**
     * word合并,返回byte[] 字节流
     * @param inputStreams
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     * @throws XmlException
     */
    protected ByteArrayInputStream wordMerge(List<InputStream> inputStreams) throws IOException, InvalidFormatException, XmlException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Map<BigInteger, BigInteger> mapTemp = new HashMap<>();
        XWPFDocument xwpfDoc = null;
        //循环处理流文件开始
        for (InputStream inputStream : inputStreams) {
            XWPFDocument xwpfDocumentOne = new XWPFDocument(inputStream);
            //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++首先处理书签签重排序-----开始++++++++++++++++++++++++++++++
            List<XWPFParagraph> paragra = xwpfDocumentOne.getParagraphs();
            for (XWPFParagraph xwpfParagraph : paragra) {
                //获取书签开始node
                List<CTBookmark> bookMarkStart = xwpfParagraph.getCTP().getBookmarkStartList();
                //获取书签结束node
                List<CTMarkupRange> bookMargEnd = xwpfParagraph.getCTP().getBookmarkEndList();
                //循环开始书签更改顺序
                for (CTBookmark ctBookmark : bookMarkStart) {
                    //获取书签当前id
                    BigInteger id = ctBookmark.getId();
                    ctBookmark.setId(BigInteger.valueOf(bookMarkCount));
                    //保存书签新设置的值与原有值,形成map
                    mapTemp.put(id, BigInteger.valueOf(bookMarkCount));
                    //新增一次,书签加1
                    bookMarkCount++;
                }
                //循环技术书签
                for (CTMarkupRange ctMarkupRange : bookMargEnd) {
                    ctMarkupRange.setId(mapTemp.get(ctMarkupRange.getId()));
                }
            }
            //++++++++++++++++++++++++++++++++++++++++++++++处理书签结束============================================
            //初次进入直接复制
            if (xwpfDoc == null) {
                xwpfDoc = xwpfDocumentOne;
            } else {
                CTBody src1Body = xwpfDoc.getDocument().getBody();
                CTBody src2Body = xwpfDocumentOne.getDocument().getBody();
                List<XWPFPictureData> allPictures = xwpfDocumentOne.getAllPictures();
                // 记录图片合并前及合并后的ID
                Map<String, String> map = new HashMap();
                for (XWPFPictureData picture : allPictures) {
                    String before = xwpfDocumentOne.getRelationId(picture);
                    //将原文档中的图片加入到目标文档中
                    String after = xwpfDoc.addPictureData(picture.getData(), Document.PICTURE_TYPE_PNG);
                    map.put(before, after);
                }

                XmlOptions optionsOuter = new XmlOptions();
                optionsOuter.setSaveOuter();
                String appendString = src2Body.xmlText(optionsOuter);
                String srcString = src1Body.xmlText();
                String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
                String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
                String sufix = srcString.substring(srcString.lastIndexOf("<"));
                String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
                //T图片替换
                if (map != null && !map.isEmpty()) {
                    //对xml字符串中图片ID进行替换
                    for (Map.Entry<String, String> set : map.entrySet()) {
                        addPart = addPart.replace(set.getKey(), set.getValue());
                    }
                }
                //将两个文档的xml内容进行拼接
                CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
                String result = makeBody.xmlText();
                src1Body.set(makeBody);
            }
        }
        xwpfDoc.write(byteArrayOutputStream);
        xwpfDoc.close();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        return byteArrayInputStream;
    }


    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        WordPoiUtil wordPoiUtil = new WordPoiUtil();
        List<InputStream> inputStreams = new ArrayList<>();
        String fileName = "G:\\toOne\\";
        try {
            File filePath = new File(fileName);
            File[] fileList = filePath.listFiles();
            for (File fileOne : fileList) {
                FileInputStream fileInputStream = new FileInputStream(fileOne);
                inputStreams.add(fileInputStream);
            }
            System.out.println(wordPoiUtil.wordMergeRetPath(inputStreams, "", ""));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

pageOffice合并

1、安装下载pageOffice,网上自行下载 pageOffice官网

原来:使用创建标签和文件插入方法。

//创建标签。标签格式固定为  PO_    不能改变
DataRegion dataNum = doc.createDataRegion("PO_begin" + (i+1),
                    DataRegionInsertType.After,"PO_begin"+i);
 /**
  *两种方式传入word,一种使用网络下载,一种是本地文件名称
 */
//dataNum.setValue("[word]downFile?path=" +files[i].getName()+ "[/word]");
  dataNum.setValue("[word]" +files[i].getPath()+ "[/word]");

全dome代码

package com.web.springbootweb.pageOffice;

import com.zhuozhengsoft.pageoffice.FileSaver;
import com.zhuozhengsoft.pageoffice.OpenModeType;
import com.zhuozhengsoft.pageoffice.PageOfficeCtrl;
import com.zhuozhengsoft.pageoffice.wordwriter.DataRegion;
import com.zhuozhengsoft.pageoffice.wordwriter.DataRegionInsertType;
import com.zhuozhengsoft.pageoffice.wordwriter.WordDocument;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: lixiao
 * Created Date: 2020/7/6 11:08
 */
@Controller
public class page {

    @RequestMapping(value = "/wordShow")
    public String wordShow() {
        return "wordShow";
    }

    /**
     * 展示简单的word页面
     * @param request
     * @param map
     * @return
     */
    @RequestMapping(value = "/word")
    public String simpleWord(HttpServletRequest request, Map<String, Object> map) {
        PageOfficeCtrl poCtrl = new PageOfficeCtrl(request);
        poCtrl.setServerPage(request.getContextPath() + "/poserver.zz");
        poCtrl.addCustomToolButton("保存", "Save", 1);
        poCtrl.addCustomToolButton("打印设置", "PrintSet", 0);
        poCtrl.addCustomToolButton("打印", "PrintFile", 6);
        poCtrl.addCustomToolButton("全屏/还原", "IsFullScreen", 4);
        poCtrl.addCustomToolButton("-", "", 0);
        poCtrl.addCustomToolButton("关闭", "Close", 21);
        poCtrl.setSaveFilePage("/save");
        poCtrl.webOpen("G:\\docTOone\\2.doc", OpenModeType.docNormalEdit, "光哥");
        map.put("pageoffice", poCtrl.getHtmlCode("PageOfficeCtrl1"));
        //跳转到word.html
        return "word";
    }


    /**
     * 文件数据合并方法
     * 例子读取文件夹下是所有文件进行合并
     * @param request
     * @param map
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/wordMarge")
    public String wordMarge(HttpServletRequest request, Map<String, Object> map) throws IOException {

        String Path = "G:\\docTOone";
        File file = new File(Path);
        File[] files = file.listFiles();
        WordDocument doc = new WordDocument();
        for (int i=0;i<files.length;i++) {
            DataRegion dataNum = doc.createDataRegion("PO_begin" + (i+1),
                    DataRegionInsertType.After,"PO_begin"+i);
            /**
             *两种方式传入word,一种使用网络下载,一种是本地文件名称
             */
            //dataNum.setValue("[word]downFile?path=" +files[i].getName()+ "[/word]");
            dataNum.setValue("[word]" +files[i].getPath()+ "[/word]");
        }
        PageOfficeCtrl pageOfficeCtrl=new PageOfficeCtrl(request);
        pageOfficeCtrl.setServerPage(request.getContextPath() + "/poserver.zz");
        pageOfficeCtrl.addCustomToolButton("保存", "Save", 1);
        pageOfficeCtrl.setSaveFilePage("save");
        pageOfficeCtrl.setWriter(doc);
        pageOfficeCtrl.webOpen("G:\\publicWordMarge.doc",OpenModeType.docNormalEdit,"nihao");
        map.put("pageoffice", pageOfficeCtrl.getHtmlCode("PageOfficeCtrl1"));
        return "wordMarge";

    }

    /**
     * 保存方法入口
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "/save")
    public String save(HttpServletRequest request, HttpServletResponse response) throws IOException {
        FileSaver fs = new FileSaver(request, response);
        FileOutputStream fileOutputStream=new FileOutputStream(new File("G:\\last.doc"));
        /**
         * 也可以获取byte字节流
         */
        fileOutputStream.write(fs.getFileBytes());
        fileOutputStream.flush();
        fileOutputStream.close();




        return "";
    }

    public static byte[] File2byte(File tradeFile){
        byte[] buffer = null;
        try
        {
            FileInputStream fis = new FileInputStream(tradeFile);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1)
            {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
        return buffer;
    }



    @RequestMapping(value = "/downFile")
    public HttpServletResponse download(String path, HttpServletResponse response) {
        try {
            // path是指欲下载的文件的路径。
            path="G:\\docTOone\\"+path;
            File file = new File(path);
            // 取得文件名。
            String filename = file.getName();
            // 取得文件的后缀名。
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();

            // 以流的形式下载文件。
            InputStream fis = new BufferedInputStream(new FileInputStream(path));
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            toClient.write(buffer);
            toClient.flush();
            toClient.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return response;
    }

}

码云地址:https://gitee.com/kissingthefire/javaBase/tree/master/src/main/java/io/fileType/word

https://gitee.com/kissingthefire/springbootweb/tree/master/src/main/java/com/web/springbootweb

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐