JAVA生成标准的Word文件(非xml格式的Word文件)

之前使用freemarker导出word,可以在PC上打开,其实也是个xml类型的,转PDF都会成为xml。但是它不能在手机上打开,因为它是xml格式的。所以后来又修改了导出方式,导出标准格式的word.

1、新建Word文件,建议直接把需要替换的值就直接写上,作为需要生成文件的模板。

2、然后把后缀名.docx改为.zip,直接就变成了个压缩包,具体的目录如下:

 

 3、因为在改为压缩包前就已经把需要替换的值给写好了,在压缩包的word文件夹里有个document.xml,该文件就是模板文件。

4、把document.xml 复制出来,跟zip文件放到同一目录下。

5、document.xml和zip都要放到生成的文件的目录下,即将要生成的文件的存放目录和zip和document.xml的目录保持一致。

6、贴上生成的工具类:其中,download方法是生成完直接下载的。makeword方法是只是生成不下载。

package com.ruoyi.project.zfwttb.controller;


import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.config.ServerConfig;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class WordAndPdfUtil {
    private static Logger logger = LoggerFactory.getLogger(WordAndPdfUtil.class);


    public static void main(String[] args) throws Exception {
        String basePath = "F:/";
        Map<String,Object> map = new HashMap<>();
        map.put("dw","zxg");
//        map.put("djq","rjk");
        makeWord(basePath, "wordToPdf.zip", "wordToPdf.docx", map);
    }


    /**
     * 生成word
     * @param basePath word所在的文件夹
     * @param wordInZipName word改为zip后word的名字
     * @param wordOutName word输出的名称
     * @param dataMap word里面需要替换的参数
     */
    public static  String makeWord(String basePath, String wordInZipName, String wordOutName, Map<String,Object> dataMap) {
        logger.info("开始创建word");
        /** 指定输出word文件的路径 **/
        String outFilePath = basePath + "data.xml";
        File docXmlFile = new File(outFilePath);

        try {
            /** 初始化配置文件 **/
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");
            /** 加载文件 **/
            configuration.setDirectoryForTemplateLoading(new File(basePath));
            configuration.setClassicCompatible(true);
            /** 加载模板 **/
            Template template = configuration.getTemplate("document.xml");
            template.setEncoding("utf-8");
            logger.info("初始化配置文件,成功, 开始渲染数据");

            /**数据渲染到word**/
            FileOutputStream fos = new FileOutputStream(docXmlFile);
            OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
            Writer out = new BufferedWriter(oWriter, 10240);
            logger.info("数据写入xml中");
            template.process(dataMap, out);
            out.close();
            fos.close();
            logger.info("数据写入xml完毕, 开始读取zip文件");

            /**读取压缩文件**/
            ZipInputStream zipInputStream = wrapZipInputStream(new FileInputStream(new File(basePath + wordInZipName)));
            /**压缩文件写入到目标路径**/
            File wordOutFile =  new File(basePath + wordOutName);
            logger.info("创建新的目录:{}", basePath + wordOutName);
            wordOutFile.createNewFile();
            ZipOutputStream zipOutputStream = wrapZipOutputStream(new FileOutputStream(wordOutFile));
            String itemName = "word/document.xml";
            /**替换参数**/
            logger.info("替换相关参数");
            replaceItem(zipInputStream, zipOutputStream, itemName, new FileInputStream(docXmlFile));
            logger.info("word生成成功");
        } catch (IOException e) {
            logger.error("IO异常:{}", e.getMessage());
            e.printStackTrace();
        } catch (TemplateException e) {
            logger.error("模板异常:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            docXmlFile.delete();
        }
        ServerConfig serverConfig = new ServerConfig();
        String url = serverConfig.getUrl()+"/profile/agzzc/"+wordOutName;
        return url;
    }

    /**
     * word转pdf
     * @param wordPath word的路径
     * @param pdfPath pdf的路径
     */
//    public static boolean wordToPdf(String wordPath, String pdfPath){
//        logger.info("wordPath:{}, pdfPath:{}", wordPath, pdfPath);
//        boolean result = false;
//        try {
//            logger.info("开始word转pdf");
//            XWPFDocument document=new XWPFDocument(new FileInputStream(new File(wordPath)));
//            File outFile=new File(pdfPath);
//            outFile.getParentFile().mkdirs();
//            OutputStream out=new FileOutputStream(outFile);
//            PdfOptions options= PdfOptions.create();
//            PdfConverter.getInstance().convert(document,out,options);
//            logger.info("word转pdf成功");
//            result = true;
//        }
//        catch (  Exception e) {
//            e.printStackTrace();
//            logger.error("word转pdf失败");
//        }
//        return result;
//    }


    public static void download( HttpServletResponse response,String basePath, String wordInZipName, String wordOutName, Map<String,Object> dataMap) {

        logger.info("开始创建word");
        /** 指定输出word文件的路径 **/
        String outFilePath = basePath + "data.xml";
        File docXmlFile = new File(outFilePath);

        try {
            /** 初始化配置文件 **/
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");
            /** 加载文件 **/
            configuration.setDirectoryForTemplateLoading(new File(basePath));
            configuration.setClassicCompatible(true);
            /** 加载模板 **/
            Template template = configuration.getTemplate("document.xml");
            template.setEncoding("utf-8");
            logger.info("初始化配置文件,成功, 开始渲染数据");

            /**数据渲染到word**/
            FileOutputStream fos = new FileOutputStream(docXmlFile);
            OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
            Writer out = new BufferedWriter(oWriter, 10240);
            logger.info("数据写入xml中");
            template.process(dataMap, out);
            out.close();
            fos.close();
            logger.info("数据写入xml完毕, 开始读取zip文件");

            /**读取压缩文件**/
            ZipInputStream zipInputStream = wrapZipInputStream(new FileInputStream(new File(basePath + wordInZipName)));
            /**压缩文件写入到目标路径**/
            File wordOutFile =  new File(basePath + wordOutName);
            logger.info("创建新的目录:{}", basePath + wordOutName);
            wordOutFile.createNewFile();
            ZipOutputStream zipOutputStream = wrapZipOutputStream(new FileOutputStream(wordOutFile));
            String itemName = "word/document.xml";
            /**替换参数**/
            logger.info("替换相关参数");
            replaceItem(zipInputStream, zipOutputStream, itemName, new FileInputStream(docXmlFile));
            logger.info("word生成成功");
        } catch (IOException e) {
            logger.error("IO异常:{}", e.getMessage());
            e.printStackTrace();
        } catch (TemplateException e) {
            logger.error("模板异常:{}", e.getMessage());
            e.printStackTrace();
        } finally {
            docXmlFile.delete();
        }

        try {
            // path是指想要下载的文件的路径
            File file = new File( basePath + wordOutName);
            // 获取文件名
            String filename = file.getName();
            // 获取文件后缀名
            String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();

            // 将文件写入输入流
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStream fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();

            // 清空response
            response.reset();
            // 设置response的Header
            response.setCharacterEncoding("UTF-8");
            //Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
            //attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
            // filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
            // 告知浏览器文件的大小
            response.addHeader("Content-Length", "" + file.length());
            OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            outputStream.write(buffer);
            outputStream.flush();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


    /**
     * 替换某个 item,
     * @param zipInputStream zip文件的zip输入流
     * @param zipOutputStream 输出的zip输出流
     * @param itemName 要替换的 item 名称
     * @param itemInputStream 要替换的 item 的内容输入流
     */
    public static void replaceItem(
            ZipInputStream zipInputStream,
            ZipOutputStream zipOutputStream,
            String itemName,
            InputStream itemInputStream){
        if(null == zipInputStream){return;}
        if(null == zipOutputStream){return;}
        if(null == itemName){return;}
        if(null == itemInputStream){return;}
        ZipEntry entryIn;
        try {
            while((entryIn = zipInputStream.getNextEntry())!=null)
            {
                String entryName =  entryIn.getName();
                ZipEntry entryOut = new ZipEntry(entryName);
                // 只使用 name
                zipOutputStream.putNextEntry(entryOut);
                // 缓冲区
                byte [] buf = new byte[8*1024];
                int len;

                if(entryName.equals(itemName)){
                    // 使用替换流
                    while((len = (itemInputStream.read(buf))) > 0) {
                        zipOutputStream.write(buf, 0, len);
                    }
                } else {
                    // 输出普通Zip流
                    while((len = (zipInputStream.read(buf))) > 0) {
                        zipOutputStream.write(buf, 0, len);
                    }
                }
                // 关闭此 entry
                zipOutputStream.closeEntry();

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //e.printStackTrace();
            close(itemInputStream);
            close(zipInputStream);
            close(zipOutputStream);
        }
    }

    /**
     * 包装输入流
     */
    public static ZipInputStream wrapZipInputStream(InputStream inputStream){
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);
        return zipInputStream;
    }

    /**
     * 包装输出流
     */
    public static ZipOutputStream wrapZipOutputStream(OutputStream outputStream){
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
        return zipOutputStream;
    }
    private static void close(InputStream inputStream){
        if (null != inputStream){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void close(OutputStream outputStream){
        if (null != outputStream){
            try {
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值