按照模板生成文件,Word 或者 Excel

news2024/11/18 3:33:53

需求流程:

    

模板部分如图:

Web端技术选用Jfinal

功能实现:

下面代码是调用 --“外部接口”--传参,将前端选中的信息传给后端, 另外将后端返回的文件流下载成文件

package ibasic.web.com.controller;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;

import com.jfinal.kit.PropKit;

import net.sf.json.JSONObject;

//excel模板
@MultipartConfig
@WebServlet("/templateExportServlet")
public class TemplateExportServlet  extends HttpServlet{
	
	

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
//		String data = req.getParameter("data");
		BufferedReader header  = req.getReader();
		StringBuffer sb = new StringBuffer();
	    String str ="" ;
        //将数据读到StringBuffer里面
	    while (null != (str = header.readLine())){
	        sb.append( str );
	    }
//	    String params = sb.toString().replaceAll("%(?![0-9a-fA-F]{2})", "%25").replaceAll("\\+", "%2B");
	
//	   String content =  URLDecoder.decode(params,"UTF-8");
		JSONObject jsonData = JSONObject.fromObject(sb.toString());
		String url = PropKit.get("template_url");
	
			RequestConfig config = RequestConfig.custom().setConnectTimeout(60000).setSocketTimeout(60000).build();
			HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
	        HttpPost post = new HttpPost(url);
	        post.setHeader("Content-Type", "application/json");
	        String result = "";
	        
	        try {
	        
	            StringEntity s = new StringEntity(jsonData.toString(), "utf-8");
	            s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
	            post.setEntity(s);
	            HttpResponse httpResponse = client.execute(post);
	            InputStream inStream = httpResponse.getEntity().getContent();
	           
	           
	            
	            
//	            BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, "utf-8"));
//	            StringBuilder strber = new StringBuilder();
//	            String line = null;
//	            while ((line = reader.readLine()) != null){
//	                strber.append(line);
//	            }
//	            inStream.close();
//	            result = strber.toString();
//	            System.out.println(result);
	            if (HttpStatus.SC_OK != httpResponse.getStatusLine().getStatusCode()) {
	            	
	            	System.out.println("请求服务端失败"); 
	            } 
	       
	       
//	        if(!"".equals(result)){
	        	 
	        	 String now = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date());
	             String fileName = String.format("%s.xlsx", now);
	        	getFileByBytes(toByteArray(inStream), PropKit.get("excel_dir"),  fileName);
	        	download(PropKit.get("excel_dir")+fileName, resp);
//	        }
	        	
	        } catch (Exception e) {
	        	
	        	e.printStackTrace();
	        }
	}
	
	public HttpServletResponse download(String path, HttpServletResponse response) {
        try {
            // 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;
    }
	
	
	 /**
     * 将Byte数组转换成文件
     **/
    public static void getFileByBytes(byte[] bytes, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            // 判断文件目录是否存在
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024*4];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }
}

下面代码实现,接收参数,生成按照模板的文件, SpringBoot实现,将模板文件ftl 放在resource目录下即可。 最后 打成jar 。部署一个地方,将这个服务的ip:port/接口名 告知上面的web去调用即可

package com.wenge.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wenge.model.Vo;
import com.wenge.util.ExcelUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @description:
 * @author: hezha
 */
@RestController
public class ExcelControll {
    @Value("${excel.dir}")
    private String dir_path ;

    @PostMapping("/downLoadExcel")
    public  byte[] downLoadExcel(@RequestBody String data){
        String msg = "";
        Map<String, Object> dataMap = new HashMap<>();

        List<Vo> list = new ArrayList<>();

        try {
            JSONObject json = JSONObject.parseObject(data);
            if(json.containsKey("news")){
                JSONArray newsArr = json.getJSONArray("news");
                for (int i = 0; i < newsArr.size(); i++) {
                    Vo vo = new Vo();
                    JSONObject jsonObject = newsArr.getJSONObject(i);
                    vo.setId(i+1);
                    vo.setTitle(jsonObject.getString("title"));
                    list.add(vo);
                }

            }

            dataMap.put("list", list);
            String now = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date());
            String fileName = String.format("%s.xlsx", now);
            System.out.println("当前导出的excel文件---->"+dir_path+fileName);
            ExcelUtils.buildExcelByTemplate("templates/excel_template.xlsx", dir_path+fileName, dataMap);
//            return dir_path+fileName;

            return getBytesByFile(dir_path+fileName);
        } catch (Exception e) {
            msg = "error";
            e.printStackTrace();
        }
//        return msg;
        return null;
    }



    //将文件转换成Byte数组
    public byte[] getBytesByFile(String pathStr) {
        File file = new File(pathStr);
        System.out.println("文件大小为: " + file.length());
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            byte[] data = bos.toByteArray();
            bos.close();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}

 

package com.wenge.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.spire.doc.Document;
import com.spire.doc.FileFormat;
import com.spire.doc.Section;
import com.spire.doc.collections.SectionCollection;
import com.spire.doc.documents.HorizontalAlignment;
import com.spire.doc.documents.Paragraph;
import com.wenge.model.Vo;

import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @description:
 * @author: hezha
 */
@RestController
public class WordController {
    @Value("${word3.dir}")
    private String dir_word3;

    @Value("${word1.dir}")
    private String dir_word1;

    @PostMapping("/downLoadWord3")
    public byte[] word3(@RequestBody String data){
        String msg = "";
        Map<String, Object> dataMap = new HashMap<>();
        List<Vo> list = new ArrayList<>();

        try {
            JSONObject json = JSONObject.parseObject(data);
            if(json.containsKey("news")){
                JSONArray newsArr = json.getJSONArray("news");
                for (int i = 0; i < newsArr.size(); i++) {
                    Vo vo = new Vo();
                    JSONObject jsonObject = newsArr.getJSONObject(i);
                    vo.setId(i+1);
                    //(信源2,阅读数xx,评论量xx)
                    String sitename = jsonObject.getString("source_name");
                    String read_count = jsonObject.getString("read_count");
                    String cmt_count  = jsonObject.getString("cmt_count");

                    vo.setDesc("("+sitename+",阅读量"+read_count+",评论量"+cmt_count+")");

                    vo.setPage_no("第"+jsonObject.getString("page_no")+"页");
                    vo.setContent(jsonObject.getString("content"));
                    list.add(vo);
                }

            }

            dataMap.put("list", list);

            String now = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date());
            String fileName = String.format("%s.docx", now);
            System.out.println("当前导出的word3文件---->"+dir_word3+fileName);

            String top_time = now.substring(0, 10).replaceAll("-", ".");
            dataMap.put("top_time", top_time);
            toWord(dataMap, dir_word3+fileName, "word3.ftl");
//            return dir_word3+fileName;
            return getBytesByFile(dir_word3+fileName);
        } catch (Exception e) {
            msg = "error";
            e.printStackTrace();
        }
//        return msg;
        return null;
    }



    @PostMapping("/downLoadWord1")
    public byte[] word1(@RequestBody String data){
        String msg = "";
        Map<String, Object> dataMap = new HashMap<>();
        List<Vo> list = new ArrayList<>();

        try {
            JSONObject json = JSONObject.parseObject(data);
            if(json.containsKey("news")){
                JSONArray newsArr = json.getJSONArray("news");
                for (int i = 0; i < newsArr.size(); i++) {
                    Vo vo = new Vo();
                    JSONObject jsonObject = newsArr.getJSONObject(i);
                    vo.setId(i+1);
                    String title = jsonObject.getString("title");
                    vo.setBlogger("作者:"+jsonObject.getString("blogger"));
                    list.add(vo);
                }

            }

            dataMap.put("list", list);

            String now = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date());
            String fileName = String.format("%s.docx", now);
            System.out.println("当前导出的word1文件---->"+dir_word1+fileName);

            String year = now.substring(0, 4);
            String month = now.substring(5, 7);
            String day = now.substring(8, 10);
            dataMap.put("year", year);
            dataMap.put("month", month);
            dataMap.put("day", day);
            toWord(dataMap, dir_word1+fileName, "word1.ftl");


            Document doc = new Document();
            doc.loadFromFile(dir_word1+fileName);


            //在文档最前面插入一个段落,写入文本并格式化
            Paragraph parainserted = new Paragraph(doc);
            doc.getSections().get(0).getParagraphs().insert(2,parainserted);
            parainserted.getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
            doc.getSections().get(0).getParagraphs().get(1).appendTOC(1,3);




            doc.updateTableOfContents();
            //保存文档
            doc.saveToFile(dir_word1+fileName, FileFormat.Docx_2010);
//            return dir_word1+fileName;
            return getBytesByFile(dir_word1+fileName);
        } catch (Exception e) {
            msg = "error";
            e.printStackTrace();
        }
//        return msg;
        return null;
    }



    public  void toWord(Map<String, Object> dataMap, String docName, String ftlName) {
        try {
            //Configuration用于读取ftl文件
            Configuration configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");

            /*以下是两种指定ftl文件所在目录路径的方式, 注意这两种方式都是
             * 指定ftl文件所在目录的路径,而不是ftl文件的路径
             */
            //指定路径的第一种方式(根据某个类的相对路径指定)
            //configuration.setClassForTemplateLoading(this.getClass(),"");
            configuration.setClassForTemplateLoading(WordController.class, "/templates");

            //指定路径的第二种方式,我的路径是C:/a.ftl
            //configuration.setDirectoryForTemplateLoading(new File("C:\\Users\\张胜强\\Desktop"));

            // 输出文档路径及名称
            File outFile = new File(docName);

            //以utf-8的编码读取ftl文件
            Template t = configuration.getTemplate(ftlName, "utf-8");
            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "utf-8"), 10240);
            t.process(dataMap, out);
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //将文件转换成Byte数组
    public byte[] getBytesByFile(String pathStr) {
        File file = new File(pathStr);
        System.out.println("文件大小为: " + file.length());
        try {
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            byte[] data = bos.toByteArray();
            bos.close();
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}
/**
     * 通过模板生成Excel文件
     * @param templateFileName 模板文件
     * @param fileName 目标文件
     * @param map 数据
     */
    public static void buildExcelByTemplate(String templateFileName, String fileName, Map map) {
        OutputStream outStream = null;
        try {
            outStream = new FileOutputStream(fileName);
            TemplateExportParams param = new TemplateExportParams(templateFileName, 0);
            Workbook workbook = ExcelExportUtil.exportExcel(param, map);
            workbook.write(outStream);
        } catch (IOException e) {
            log.error("根据模板生成Excel文件失败, 失败原因: {}", e);
        } finally {
            try {
                if (outStream != null) {
                    outStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1419522.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

链表--114. 二叉树展开为链表/medium 理解度C

114. 二叉树展开为链表 1、题目2、题目分析3、复杂度最优解代码示例4、适用场景 1、题目 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而…

ChatGPT更新了Mention功能,集结若干GPTs作战,AI智能体的心智入口;向量数据库的挑战和未来

&#x1f989; AI新闻 &#x1f680; ChatGPT更新了Mention功能&#xff0c;集结若干GPTs作战&#xff0c;AI智能体的心智入口 摘要&#xff1a;OpenAI在ChatGPT中引入了一个新功能&#xff0c;允许用户在聊天时任意一个GPTs&#xff08;即ChatGPT最新推出的AI Agent 智能应用…

Java 对部分接口返回数据进行加密,或其他处理

业务场景&#xff1a;后端项目中分为PC端和移动端接口&#xff0c;移动端为例如 mobile 开头的URl&#xff0c;需求为调用移动端接口时&#xff0c;对返回数据进行加密&#xff0c;PC端不加密 import cn.hutool.core.date.DatePattern; import cn.hutool.json.JSONConfig; impo…

HiveSQL题——排序函数(row_number/rank/dense_rank)

一、窗口函数的知识点 1.1 窗户函数的定义 窗口函数可以拆分为【窗口函数】。窗口函数官网指路&#xff1a; LanguageManual WindowingAndAnalytics - Apache Hive - Apache Software Foundationhttps://cwiki.apache.org/confluence/display/Hive/LanguageManual%20Windowin…

力扣题集(第一弹)

一日练,一日功;一日不练十日空。 学编程离不开刷题&#xff0c;接下来让我们来看几个力扣上的题目。 1. 242. 有效的字母异位词 题目描述 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数…

粒子群算法求解港口泊位调度问题(MATLAB代码)

粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;它通过模拟鸟群或鱼群的行为来寻找最优解。在泊位调度问题中&#xff0c;目标是最小化所有船只在港时间的总和&#xff0c;而PSO算法可以帮助我们找到一…

07. STP的基本配置

文章目录 一. 初识STP1.1. STP概述1.2. STP的出现1.3. STP的作用1.4. STP的专业术语1.5. BPDU的报文格式1.6. STP的选择原则&#xff08;1&#xff09;选择根桥网桥原则&#xff08;2&#xff09;选择根端口原则 1.7. 端口状态1.8. STP报文类型1.9. STP的收敛时间 二. 实验专题…

如何获得《幻兽帕鲁》隐藏帕鲁唤夜兽?13000个配种配方查询 幻兽帕鲁Steam好评率还在涨 Mac苹果电脑玩幻兽帕鲁 Crossover玩Windows游戏

《幻兽帕鲁》是一款Steam平台热门游戏&#xff0c;开放式大陆和养成式冒险结合&#xff0c;成为2024首款热门游戏&#xff0c;不过由于官方仅发布了Windows版的游戏客户端&#xff0c;Mac用户无法直接玩&#xff0c;好在有Crossover这样的神器&#xff0c;让苹果电脑也能玩上《…

U-Boot学习(6):初始化之_main函数源码分析

在上一节系统初始化之start.S源码分析详解中&#xff0c;我们分析了上电后的代码执行流程&#xff0c;实际上就是对系统特权模式、CP15、向量表等进行配置。最后一步就是进入_main函数了&#xff0c;这个就是U-Boot的主程序了&#xff0c;它完成了对系统内存、堆栈、全局结构体…

非常好用的高效率截图工具-Snipaste

官网:https://zh.snipaste.com/ 帮助文档: https://docs.snipaste.com/zh-cn/

已实现:vue、h5项目如何使用echarts实现雷达图、六边形图表

说实话&#xff0c;要说图表里&#xff0c;最强的应该属于echarts了&#xff0c;不管是接入难度上&#xff0c;还是样式多样性上&#xff0c;还有社区庞大程度上&#xff0c;都是首屈一指的&#xff0c;反观有的人习惯用chart.js了&#xff0c;这个无可厚非&#xff0c;但是如果…

Glide完全解读

一&#xff0c;概述 glide作为android流行的图片加载框架&#xff0c;笔者认为有必要对此完全解读。glide提供了三级缓存、生命周期Destroy后自动移除缓存、自动适配ImageView&#xff0c;以及提供了各种对图片修饰的操作&#xff0c;如剪裁等。本文通过最简单的使用&#xff…

Vim实战:使用 Vim实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

光学3D表面轮廓仪服务超精密抛光技术发展

随着技术的不断进步&#xff0c;精密制造领域对材料表面的处理要求越来越高&#xff0c;超精密抛光技术作为当下表面处理的尖端技术&#xff0c;对各种高精密产品的生产起到了至关重要的作用&#xff0c;已广泛应用于集成电路制造、医疗器械、航空航天、3C电子、汽车、精密模具…

Django知识随笔

目录 1.如何再ajax中传输post数据&#xff1f; 2.在form表单中使用jquery序列化&#xff0c;input框过多。 1.如何再ajax中传输post数据&#xff1f; 在ajax传递的那个网址&#xff0c;会调用你路由的视图函数&#xff0c;在视图函数上面加一句 csrf_exempt 。写上之后会有提…

Docker私有仓库搭建

目录 搭建本地私有仓库 Docker--harbor私有仓库部署与管理 Harbor 简介 什么是Harbor Harbor的特性 Harbor的构成 Harbor 部署 部署 Docker-Compose 服务 ​编辑部署 Harbor 服务 启动 Harbor 进入浏览器http://192.168.20.10进入harbor的客户端 搭建本地私有仓库 …

Shell中sed编辑器

1.简介 sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。 sed编辑器可以根据命令来处理数据流中的数据&#xff0c;这些命令要么从命令行中输入&#xff0c;要么存储在一个 命令文本文件中。 2.sed编辑器的工作流程 sed…

12.从项目经理的生存哲学到适配器模式(Adapter Pattern)

如果这个世界没有了项目经理&#xff0c;事情的发展可能并不会如同想象中一样美好&#xff0c;相反&#xff0c;对于开发人员来说可能是噩梦的开始。 比如&#xff1a; 客户因为几个需求的具体实现大发雷霆&#xff0c;甚至开始恶语相向&#xff0c;一通含ma量极高的“斯伯坦语…

【EEG信号处理】ERP相关

ERP&#xff0c;全称为event-related potential&#xff0c;中文是事件相关电位。 首先要明确的一点是&#xff0c;ERP是根据脑电图EEG得到的&#xff0c;他是EEG的一部分&#xff0c;是最常用的时域分析方法 可能有一部分是介绍不到的&#xff0c;望谅解 在维基百科中给的定义…

Vue3的v-model

目录 基本用法 底层机制 v-model 的参数 多个 v-model 绑定 处理 v-model 修饰符 带参数的 v-model 修饰符 例子 总结&#xff1a;Vue 3 中的 v-model 指令与 Vue 2 中的 v-model 相比有一些变化和改进。最显著的变化是&#xff0c;在 Vue 3 中&#xff0c;v-model 可以…