JAVAはFreemarkテンプレートと連携してワードリターンファイルストリームを生成し、フロントデスクのvueがダウンロードを受信します

単語を生成するためのFreemarkテンプレートのアイデアはPOIのアイデアに似ていますが、Freemarkの機能はPOIよりも強力です。

POIについては、前の記事を参照してください:https//blog.csdn.net/CarryBest/article/details/94630824

1つ:最初にテンプレートを作成します

   新しい単語テンプレートを作成し、その中に必要な形式を作成します。変数名を直接記述してxmlとして保存し、xml、Baiduを開いてデータをxml形式でフォーマットし、変数が混乱していないかどうかを確認します。めちゃくちゃ、手動で元に戻します。

最も基本的なのはこの使用法であり、変数をNullと判断できます。その他の処理

特定の変数をループさせたい場合は、<#list connmlist asconnms>を使用できます</#list>この種の記述、connmlistは、Javaバックエンドの変数connmsです。connmは、Javaバックエンドのデータ形式が次のようになっていることを意味します対応する色でマークを付けることができます。

connmMap.put("connm", wqDataEditsData.getConnm());
connmList.add(connmMap);

resultMap.put( " connmlist "、connmList);

 

2:新しいパブリックメソッドDocumentHandler.javaを作成します

package com.XX.XXXX.documentHandler;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

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

/**
 * 类描述:
 *
 * @author :carry
 * @version: 1.0  CreatedDate in  2019年10月12日
 * <p>
 * 修订历史: 日期			修订者		修订描述
 */
public class DocumentHandler {
    private Configuration configuration = null;

    public DocumentHandler() {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
    }

    public void createDoc( Map<String ,Object > result,String fileName,String inPath,String outPath) throws Exception {
        configuration.setDefaultEncoding("utf-8");
        //模板方在项目的resource下的template里面
       // configuration.setClassForTemplateLoading(this.getClass(), "/template");
        //模板放在项目的盘符下
        configuration.setDirectoryForTemplateLoading(new File(inPath));
        System.out.println("文件路径"+outPath);
        Template t = null;
        try {
            t = configuration.getTemplate(fileName,"utf-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
        File outFile = new File(outPath);
        Writer out = null;
        try {
              out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            t.process(result, out);
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @方法描述:
     * path 下载的文件路径  projectname  这里意义不大 直接被vue前台替换了   suffix后缀名  这里意义不大 直接被vue前台替换了
     * @return: javax.servlet.http.HttpServletResponse
     * @Author: carry
     */
    public HttpServletResponse download(String downloadPath, HttpServletResponse response) throws Exception {
        // 以流的形式下载文件。
        InputStream fis = new BufferedInputStream(new FileInputStream(downloadPath));
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        fis.close();
        response.reset();
        // 设置response的Header  这里意义不大 直接被vue前台替换了 所以可以删掉
        response.addHeader("Content-Disposition", "attachment;filename="
                +"test"+ new String(("" + ".docx").getBytes("gbk"),
                "iso-8859-1"));
        OutputStream toClient = new BufferedOutputStream(
                response.getOutputStream());
        //注意这里很重要 vue的回调里根据ContentType类判断是否是下载的操作,这里不要改
        response.setContentType("application/octet-stream");
        toClient.write(buffer);
        toClient.flush();
        this.close(fis);
        this.close(toClient);
        return response;
    }


    /**
     *  关闭输入流
     * @param is
     */
    private void close(InputStream is) {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *  关闭输出流
     * @param os
     */
    private void close(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3:クラスの呼び出し:

// 数据库里的数据与xml映射起来getLogsData这个方法就省略了,意思很清楚,就是你xml里有叫${name}的,那么java的map里也要响应的放一个键值对的键叫name的。
 Map<String, Object> resultMap = this.getLogsData(params);
 /**
     * @方法描述: 下载导出整编数据
     * @return: void
     * @Author: carry
     */
    @GetMapping("/exportToWordByFmk")
    public void exportToWordByFmk(HttpServletRequest request,
                                  HttpServletResponse response,
                                  @RequestParam(value = "tm", required = true) String tm) {
        try {
            Map<String, String> params = new HashMap<String, String>();
            params.put("tm", tm);

            String path = ResourceUtils.getURL("classpath:").getPath();
            //项目获取盘符
            String root =path.substring(1,3);
            //创建生成的目录
            File outPathFile = new File(root+"\\jddsFile\\docResults");
            if (!outPathFile.exists()) {
                outPathFile.mkdirs();
            }
            //创建读取模板的目录
            File inPathFile = new File(root+"\\jddsFile\\docTemplate");
            if (!inPathFile.exists()) {
                inPathFile.mkdirs();
            }
           //模板名称
            String fileName = "WQDataEditsDataTmpFmk.xml";
            //输出模板名字,java生成的文件名字,前台会被vue替换掉
            String outPath =outPathFile.getAbsolutePath()+"\\WQDataEditsData.docx";
            String inPath =inPathFile.getAbsolutePath();
           // 讲数据库里的数据与xml映射起来
            Map<String, Object> resultMap = this.getLogsData(params);

            DocumentHandler dh = new DocumentHandler();
            dh.createDoc(resultMap, fileName,inPath, outPath);
            dh.download(outPath, response);

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

    }

4:vueの呼び出し

   downloadFiles(row) {
                let params = {};
               
                this.$api.exportToWordByFmk(params).then(res => {
                    if (res.code == "0") {
                        let data = res.result.data;
                        let blob = new Blob([data], {
                            //type   mimi类型  可以百度详细类型
                            //word文档为msword,application/pdfpdf文档为pdf  application/vnd.ms-excel
                            //image/jpeg jpg
                          //  type: `msword`
                            type: `application/msword`
                        });
                        let objectUrl = URL.createObjectURL(blob);
                        let link = document.createElement("a");
                        let fname = "测试";
                        link.href = objectUrl;
                        link.setAttribute("download", fname);
                        document.body.appendChild(link);
                        link.click();
                    } else {
                        this.$message.error(res.msg);
                    }
                });
            },

5:ファイルストリームを受信するカプセル化されたvueの方法

 //ここで、バックエンドがファイルストリームの形式で戻る場合、カスタムリターンコンテンツは応答ファイルストリームにスプライスされます

            contentType = headers ['content-type'];

            if(contentType == "application / octet-stream"){

                resultData = dataとします。

                stdRs = {"code":0、 "msg": "操作成功"、 "result":{"data":resultData}}

            }

  //核心请求函数,并做拦截处理。
    // config: {url,method,params,data,timeout,headers,message,loading}
    // resp: {data:{},status:200,statusText:'OK',headers:{},config:{},request:{}}
    request(config) {
        this.onStart(config);
        return this.http.request(config).then((res) => {
            let {data, headers, request, status, statusText} = res;
            let stdRs = null;
            //此处如果后台返回的是文件流的形式,则自定义返回内容拼接上response的文件流
            let contentType=headers['content-type'];
            if(contentType=="application/octet-stream"){
                let resultData=data;
                stdRs={"code":0,"msg":"操作成功","result":{ "data":resultData}}
            }else{
                try {
                    stdRs = JSON.parse(data);
                } catch (e) {
                    stdRs = this.stdRs(status + '', statusText, data);
                }
               
            }

            this.onComplete(config, stdRs);
            return this.resultSuccess(stdRs) ? Promise.resolve(stdRs) : Promise.reject(stdRs);
        }).catch((err) => {
            if (!err.response && !err.request) {
                return Promise.reject(err);
            }
            let {request, response} = err;
            let {status, statusText} = response;
            let stdRs = this.stdRs(status + '', statusText, null);
            this.onComplete(config, stdRs);
            return Promise.reject(stdRs);
        });
    }
 //导出文件
    export(config) {
        if (config.data) {
            config.responseType="blob";
            config.params = {...config.params, ...config.data};
            if(config.data.params != undefined){
                config.params={ ...config.params,...config.data.params}
            }

            delete config.data;
        }
        return this.request(config);
    }

 

おすすめ

転載: blog.csdn.net/CarryBest/article/details/102586653