(不需要copy代码,请专注于理解如何实现,我会详细解释代码!)

一、简要描述
  One day,我参与的项目中,用户提了个新需求。要求:按照给定 word模板,填充数据并导出。

  负责这个需求后,我查阅CSDN,虽然也找到了一些文章,依据文章中的顺序,写出了demo。但demo毕竟是demo,在项目实战中,还是让我遇到不少坑。

  由于 easypoi对Word的支持不太友好,不支持多图片导出,因此研究之后,也找到一个办法,后续会展开叙述。

二、项目描述
  主要涉及:SpringBoot + MySQL + Linux

  实际项目会部署在Linux上,图片也是需要从服务器上解析到本地,转成Base64位字节才可以。不过我会提供全部的图片转Base64公共方法。

注意理解:Word支持显示的图片,是图片通过IO流转成的Base64字节

(正式开始 ===> follow me!)

第一步:准备Word模板

第二步:导入Jar包

        <!-- 集成 easypoi --><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>3.3.0</version></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-web</artifactId><version>3.3.0</version></dependency><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-annotation</artifactId><version>3.3.0</version></dependency>

第三步:Controller层 接口

 @ApiOperation(value = "导出巡查整改通知单")@PostMapping("/letter/notice/export")@ApiImplicitParams({@ApiImplicitParam(name = "id", value = "巡查id")})public void wordExport(@RequestParam Long id,HttpServletRequest request, HttpServletResponse response) throws IcmsException, IOException {// 注入Service层service.wordExport(id, request, response);}

第四步:Service层 业务

    @Overridepublic void wordExport(Long id, HttpServletRequest request, HttpServletResponse response) throws IcmsException, IOException {// 1.查询数据User user = userDao.selectList(new QueryWrapper<User>().eq("id",id));// 2.创建 mapMap<String,Object> data = new HashMap<>();data.put("number",new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())); // 通知单号data.put("unitName", StringUtils.isEmpty(user.getUnitName()) ? " ":user.getUnitName()); // 单位data.put("sendTime",null == user.getSendTime() ? " ":new SimpleDateFormat("yyyy年MM月dd日HH时mm分ss秒").format(user.getSendTime()));data.put("type",StringUtils.isEmpty(user.getType()) ? " ":user.getType()); // 问题类型data.put("content",StringUtils.isEmpty(user.getContent()) ? " ":user.getContent()); // 问题描述// 3.处理图片String httpPath = request.getScheme() + "://" + request.getServerName() + user.getUrl();  // 图片路径WordImageEntity image = new WordImageEntity(FileUtils.getImageBase64(httpPath),384,216);image.setType(WordImageEntity.Data); // 设置成 Byte字节data.put("image",image);// 4.导出FileUtils.easyPoiExport("/opt/baidu/web/file/word/template.docx","tempDir","test.docx",data,request,response);}

描述:
1、进入Service层,第一步是查询本次需要导出的数据。
2、创建map的作用:easypoi会通过map的key值,映射到word模板上,替换value值。

重要
真正在写业务的时候,请注意对替换的值,进行判空处理!如果值为空,请使用“ ”,而不是“”。中间要空格!

图片
代码中的 String httpPath = “”,由于我的项目部署在Linux服务器上,图片也在服务器中,需要获取全路径。Windows系统本地开发,可使用本地图片全路径。

String httpPath = request.getScheme() + "://" + request.getServerName() + file.getUrl();输出结果:http://172.16.231.188/file/img/2020-03-29/161699762599480.jpg

WordImageEntity 详解
  1、WordImageEntity类提供了2个构造方法,一个可直接传图片URl,一个传图片字节byte[]。此处建议使用public WordImageEntity(byte[] data) --缩写构造方法。

  2、WordImageEntity类支持设置图片宽度、高度。

关于FileUtils.getImageBase64()这个方法继续往下看会讲到。

第五步:FileUtils

通用工具类
public class FileUtils {/*** EasyPoi 替换数据 导出 word* @param templatePath word模板地址* @param tempDir      临时文件存放地址* @param filename     文件名称* @param data         替换参数* @param request* @param response*/public static void easyPoiExport(String templatePath, String tempDir, String filename, Map<String, Object> data, HttpServletRequest request, HttpServletResponse response) {Assert.notNull(templatePath, "模板路径不能为空");Assert.notNull(tempDir, "临时文件路径不能为空");Assert.notNull(filename, "文件名称不能为空");Assert.isTrue(filename.endsWith(".docx"), "文件名称仅支持docx格式");if (!tempDir.endsWith("/")) {tempDir = tempDir + File.separator;}File file = new File(tempDir);if (!file.exists()) {file.mkdirs();}try {String userAgent = request.getHeader("user-agent").toLowerCase();if (userAgent.contains("msie") || userAgent.contains("like gecko")) {filename = URLEncoder.encode(filename, "UTF-8");} else {filename = new String(filename.getBytes("utf-8"), "ISO-8859-1");}XWPFDocument document = WordExportUtil.exportWord07(templatePath, data);String tempPath = tempDir + filename;FileOutputStream out = new FileOutputStream(tempPath);document.write(out);// 设置响应规则response.setContentType("application/force-download");response.addHeader("Content-Disposition", "attachment;filename=" + filename);OutputStream stream = response.getOutputStream();document.write(stream);stream.close();} catch (Exception e) {e.printStackTrace();} finally {deleteTempFile(tempDir, filename);}}/*** 删除临时生成的文件*/public static void deleteTempFile(String filePath, String fileName) {File file = new File(filePath + fileName);File f = new File(filePath);file.delete();f.delete();}
}

至此,按照以上顺序,即可完成 easypoi 导出 word!

三、扩展

1、图片转字节数组(Linux生产环境、本地开发环境)

  /*** Linux生产环境 将图片转换为字节数组* @param path 文件 http路径* @return base64编码过的字节数组* @throws IOException*/public static byte[] getImageBase64(String path) throws IOException {byte[] data = null;URL url = null;InputStream input = null;try{url = new URL(path);HttpURLConnection httpUrl = (HttpURLConnection) url.openConnection();httpUrl.connect();httpUrl.getInputStream();input = httpUrl.getInputStream();}catch (Exception e) {e.printStackTrace();return null;}ByteArrayOutputStream output = new ByteArrayOutputStream();byte[] buf = new byte[1024];int numBytesRead = 0;while ((numBytesRead = input.read(buf)) != -1) {output.write(buf, 0, numBytesRead);}data = output.toByteArray();output.close();input.close();return data;}
   /*** 本地开发环境 将图片转换为字节数组存储* @param path 文件 http路径* @return base64编码过的字节数组* @throws IOException*/public static byte[] getImageBase64(String path) throws IOException {InputStream input = new FileInputStream(path);ByteArrayOutputStream output = new ByteArrayOutputStream();byte[] buf = new byte[1024];int numBytesRead = 0;while ((numBytesRead = input.read(buf)) != -1) {output.write(buf, 0, numBytesRead);}byte[] data = output.toByteArray();output.close();input.close();return data;}

2、多图片导出(easypoi 并不支持多图片导出,以下仅供参考!)

(1)修改模板

由于 easypoi并不支持多图片导出,因此该模板与原先模板不同之处就在于,在显示图片的地方,多定义标签,并设置下标。

(2)业务层代码

 // 1.全部图片信息 filesList<FileInfoModel> files = detail.getFiles();if(null != files && files.size() > 0){ List<WordImageEntity> images = new ArrayList<>();for (FileInfoModel file : files) {// 2.处理每一张图片,并将其添至 images集合中String httpPath = request.getScheme() + "://" + request.getServerName() + file.getUrl();  // 图片路径WordImageEntity image = new WordImageEntity(FileUtils.getImageBase64(httpPath),384,216);image.setType(WordImageEntity.Data);images.add(image);}// 3.图片赋值for (int i = 0; i < images.size(); i++) {data.put("image_"+i, images.get(i));}// 4.多余 {{image_x}} 标签要赋值为空for (int i = images.size(); i < 5; i++) {data.put("image_"+i, " ");}}else{// 5.如果没有图片,所有图片标签置空for (int i = 0; i < 5; i++) {data.put("image_"+i, " ");}}

如果你对于 easypoi所实现的效果不满意,可以选择使用 freemarker技术来生成 word文档。
为此我也撰写了一份博客:Freemarker word 导出

至此,完結~

EasyPoi word导出教程相关推荐

  1. EasyPoi word导出 简易使用指南

    代码的功能介绍在注释中 0.整理思路 (1)前端按钮调用后端控制类 (2)前端:传递参数,接受返回的文件并下载到本地 (3)后端:接受传递过来的参数,查找出对应的实体类,通过easypoi提供的模板和 ...

  2. SpringBoot+EasyPOI word模板导出,含多张图片

    这几天客户提出了新的需求,要求记录要能够导出word,并且里面包含的图片也要导出来,这里借用EasyPOI来进行操作. 参考文章:https://blog.csdn.net/qq_34752942/a ...

  3. EasyPoi模板导出word(简单文本、内嵌表格、循环图片)

    EasyPoi模板导出word(简单文本.内嵌表格.循环图片) 先上效果图 模板在此 依赖导入 *坑:注意依赖版本 4.3.0+才支持多图片循环导出 <!-- word导出 方式:easypoi ...

  4. freemarker模板导出带表格word详细教程

    前言:另外一篇是手机端的word导出,需要兼容性,不然在安卓手机会乱码 freemarker模板导出word循环图片表格详细教程_Java大表哥的博客-CSDN博客  并且另存为模版格式不同数据绑定方 ...

  5. 使用EasyPoi导入导出Excel

    easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员 就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板 语言( ...

  6. 使用easypoi导入导出excel,SSM和SpringBoot通用代码

    easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员就可以方便的写出Excel导出,Excel模板导出,Excel导入,Word模板导出,通过简单的注解和模板语言(熟悉 ...

  7. Word导出PDF—保留图片高分辨率同时不丢失书签/超链接

    文章目录 一.打印高质量PDF文件(无书签.超链接) 二.设置书签.超链接 三.小结 参考资料 一.打印高质量PDF文件(无书签.超链接) ① 安装Adobe Acrobat(本人使用的是Adobe ...

  8. phpword 模板替换并导出教程

    phpword 模板替换并导出教程 word 模板文件定义 楼主在 public\uploads\application\template.docx 该路径下面创建了 word 的模板文件templa ...

  9. 使用EasyPOI导入导出报表

    简介 easypoi功能如同名字easy,主打的功能就是容易,让一个没见接触过poi的人员,就可以方便的写出Excel导出,Excel模板导出,Excel导入,word模板导出,通过简单的注解和模板 ...

最新文章

  1. python使用缩进作为语法边界一般建议怎样缩进-Python基础自测挑战题
  2. 【正一专栏】欧冠决赛点评——只服齐达内,送别布冯
  3. tensorflow从入门到精通100讲(一)-如何申明一个tensor,Tensorflow中最重要的基本操作
  4. tkFileDialog报错,模块未找到出错:没有名字叫做 tkFileDialog 的模块
  5. 16进制、10进制(n进制)转换为二进制
  6. ubuntu 18.04安装绿联千兆USB网卡的AX88179芯片驱动(编译报错解决)
  7. java做一个客房管理系统定制_基于jsp的客房管理系统-JavaEE实现客房管理系统 - java项目源码...
  8. 第1章.绪论(计算机科学导论)
  9. PHP 图片转PDF
  10. PHP中的日期相减函数,在php中有没有日期相减的函数
  11. 静态代理和动态代理的区别,什么场景使用?
  12. matlab 三维图形改变线宽,用PANDAS改变线宽绘制三维线图
  13. 生日提醒功能-提前三天
  14. Visio2013 补丁
  15. 工程伦理 清华慕课网答案
  16. 制作自动添加IE信任站点运行文件
  17. 群晖硬盘扩容 逃课方法
  18. 甜椒刷机助手(安卓一键刷机助手) v3.5.1.1 电脑版
  19. 服务器信息怎么备份,DNS服务器信息备份与还原教程
  20. Unity两点距离计算

热门文章

  1. Java程序员工作三年以内
  2. 蓝桥基础练习 特殊的数字 JAVA
  3. PyTorch随机生成一个布尔型张量
  4. java生成图片,特殊字符显示方框问题解决
  5. Testflight上架丨苹果官方内测渠道详解
  6. 冯森林:手机淘宝中的那些Web技术
  7. 部署社区版deepflow
  8. Office 2016 Pro Plus \ Project 专业版 \ Visio 专业版 \ 64 位vol版本方便KMS小马oem
  9. IPV6 邻居发现协议(NDP)
  10. 计算机毕业设计JAVA网上童装销售系统mybatis+源码+调试部署+系统+数据库+lw