【操作word】Java + POI导出富文本的内容到word文档
这周工作中,遇到一个需求是需要将数据库中富文本内容导出到word文档里面,于是就采用POI技术实现了一下导出word文档的功能。(word文档是识别html内容的,所以富文本内容也自然能够识别。)
一、准备工作
采用技术介绍:
- Java + POI
- Jsoup(主要是解析图片标签,然后缩放图片大小,下文有介绍)
<!-- jsoup依赖-->
<dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.12.1</version>
</dependency>
<!-- poi依赖-->
<dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.0</version>
</dependency>
<dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.0</version>
</dependency>
二、具体步骤
(1)Word工具类
采用POI组件编写一个导出word的工具类。
package com.gitee.zhuyb.richtext.word;import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;/*** @author: ZhuYouBin* @date: 2022/1/13 10:21* @description: poi操作word工具类*/
public class WordUtil {/*** 导出富文本内容到word* @param request* @param response* @param content 输出内容* @param fileName 导出文件名称* @throws Exception*/public static void exportHtmlToWord(HttpServletRequest request, HttpServletResponse response, String content, String fileName) throws Exception {// 拼接html格式内容StringBuffer sbf = new StringBuffer();// 这里拼接一下html标签,便于word文档能够识别sbf.append("<html " +"xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" xmlns:m=\"http://schemas.microsoft.com/office/2004/12/omml\" xmlns=\"http://www.w3.org/TR/REC-html40\"" + //将版式从web版式改成页面试图">");sbf.append("<head>" +"<!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:TrackMoves>false</w:TrackMoves><w:TrackFormatting/><w:ValidateAgainstSchemas/><w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid><w:IgnoreMixedContent>false</w:IgnoreMixedContent><w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText><w:DoNotPromoteQF/><w:LidThemeOther>EN-US</w:LidThemeOther><w:LidThemeAsian>ZH-CN</w:LidThemeAsian><w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript><w:Compatibility><w:BreakWrappedTables/><w:SnapToGridInCell/><w:WrapTextWithPunct/><w:UseAsianBreakRules/><w:DontGrowAutofit/><w:SplitPgBreakAndParaMark/><w:DontVertAlignCellWithSp/><w:DontBreakConstrainedForcedTables/><w:DontVertAlignInTxbx/><w:Word11KerningPairs/><w:CachedColBalance/><w:UseFELayout/></w:Compatibility><w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel><m:mathPr><m:mathFont m:val=\"Cambria Math\"/><m:brkBin m:val=\"before\"/><m:brkBinSub m:val=\"--\"/><m:smallFrac m:val=\"off\"/><m:dispDef/><m:lMargin m:val=\"0\"/> <m:rMargin m:val=\"0\"/><m:defJc m:val=\"centerGroup\"/><m:wrapIndent m:val=\"1440\"/><m:intLim m:val=\"subSup\"/><m:naryLim m:val=\"undOvr\"/></m:mathPr></w:WordDocument></xml><![endif]-->" +"</head>");sbf.append("<body>");// 富文本内容sbf.append(content);sbf.append("</body></html>");// 必须要设置编码,避免中文就会乱码byte[] b = sbf.toString().getBytes("GBK");// 将字节数组包装到流中ByteArrayInputStream bais = new ByteArrayInputStream(b);POIFSFileSystem poifs = new POIFSFileSystem();DirectoryEntry directory = poifs.getRoot();// 这代码不能省略,否则导出乱码。DocumentEntry documentEntry = directory.createDocument("WordDocument", bais);//输出文件request.setCharacterEncoding("utf-8");// 导出word格式response.setContentType("application/msword");response.addHeader("Content-Disposition", "attachment;filename=" +new String(fileName.getBytes("GB2312"),"iso8859-1") + ".doc");ServletOutputStream ostream = response.getOutputStream();poifs.writeFilesystem(ostream);bais.close();ostream.close();}}
(2)图片工具类
图片工具类,主要是用于缩放图片大小,这里缩放图片采用的是java中awt包下提供的图像处理类。
假设富文本中又包含base64编码的图片,这时候要导出到word文档中,图片如果太大,导出word时候图片会超出word范围,就像下面所示:
ImageUtils工具类代码如下:
package com.gitee.zhuyb.richtext.word;import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;/*** @author: ZhuYouBin* @date: 2022/1/13 15:01* @description: 图片处理工具类*/
public class ImageUtils {/*** 通过BufferedImage图片流调整图片大小*/public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException {Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_AREA_AVERAGING);BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);return outputImage;}/*** 返回base64图片* @param data* @return*/public static String imageToBase64(byte[] data) {BASE64Encoder encoder = new BASE64Encoder();// 返回Base64编码过的字节数组字符串return encoder.encode(data);}/*** base64转换成byte数组* @param base64* @return* @throws IOException*/public static byte[] base64ToByte(String base64) throws IOException {BASE64Decoder decoder = new BASE64Decoder();// 返回Base64编码过的字节数组字符串return decoder.decodeBuffer(base64);}/*** BufferedImage图片流转byte[]数组*/public static byte[] imageToBytes(BufferedImage bImage) {ByteArrayOutputStream out = new ByteArrayOutputStream();try {ImageIO.write(bImage, "png", out);} catch (IOException e) {e.printStackTrace();}return out.toByteArray();}/*** byte[]数组转BufferedImage图片流*/public static BufferedImage bytesToBufferedImage(byte[] ImageByte) {ByteArrayInputStream in = new ByteArrayInputStream(ImageByte);BufferedImage image = null;try {image = ImageIO.read(in);} catch (IOException e) {e.printStackTrace();}return image;}
}
(3)导出word
这里采用web下载的方式导出word文档。
这里先给出用于测试的富文本内容数据:
<h1>如何将富文本内容导出到word文档</h1><p style="color:red;font-size:20px;">采用poi将富文本内容导出到word文档</p><div style="background-color:green;">这是有背景颜色的div内容</div>
<img src="这里写base64后的图片编码">这是base64编码后的图片
首先将图片转换成base64编码,然后把编码赋值到上面的【img】标签中的【src】属性里面即可测试。
因为直接将这些测试数据赋值给静态字符串,无法编译,所以下面为了测试,首先通过文件读取富文本内容。(实际开发中,富文本内容都是直接从数据库中获取,所以无需操作文件)
package com.gitee.zhuyb.richtext.word;import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;/*** @version 1.0.0* @Description: #类描述* @Date: 2022/1/16 13:57* @Copyright (C) ZhuYouBin*/
@RestController
@RequestMapping("/export")
public class ExportController {@RequestMapping(value = "/exportWord")public void export(HttpServletRequest request, HttpServletResponse response)throws Exception {try {String tmpContent = "";// 获取img图片标签// 1.Jsoup解析htmlDocument document = Jsoup.parse(tmpContent);// 获取所有img图片标签Elements img = document.getElementsByTag("img");int index = 0;List<String> imgBase64List = new ArrayList<>();for (Element element : img) {imgBase64List.add(element.attr("src"));// 处理特殊符号String attrData = element.attr("src");// base64编码后可能包含 + 特殊字符,所以需要转义attrData = attrData.replaceAll("\\+", "\\\\+");tmpContent = tmpContent.replaceAll(attrData, "{{image_src" + index + "}}");index++;}// 缩放图片大小,然后重新base64编码后替换到富文本内容里面导出wordindex = 0;String prefix = "data:image/png;base64,"; // base64编码前缀for (String base64 : imgBase64List) {if (StringUtils.isNotBlank(base64)) {// 缩小图片base64 = base64.replaceAll(prefix, "");BufferedImage bufferedImage = ImageUtils.bytesToBufferedImage(ImageUtils.base64ToByte(base64));if (bufferedImage == null) {tmpContent = tmpContent.replaceAll("\\{\\{image_src" + index + "}}", "");} else {int height = bufferedImage.getHeight();int width = bufferedImage.getWidth();// 如果图片宽度小于700,则图片不缩放,还是使用原图片if (width > 700) {BufferedImage imgZoom = ImageUtils.resizeImage(bufferedImage, 700, height);String imageToBase64 = ImageUtils.imageToBase64(ImageUtils.imageToBytes(imgZoom));tmpContent = tmpContent.replaceAll("\\{\\{image_src" + index + "}}", prefix + imageToBase64);} else {tmpContent = tmpContent.replaceAll("\\{\\{image_src" + index + "}}", prefix + base64);}}} else {tmpContent = tmpContent.replaceAll("\\{\\{image_src" + index + "}}", "");}index++;}// 执行导出操作WordUtil.exportHtmlToWord(request, response, tmpContent, "富文本内容导出word");} catch (Exception e) {e.printStackTrace();}}}
(4)如何解决图片太大的问题
前面说了,导出富文本中的base64图片时候,如果图片太大,导出到word中就会很大,导致word很难看,那有什么解决办法呢?
解决方案:
- 将图片缩放后,在将新的base64编码导出到word中
- 采用jsoup提取富文本中的所有【img】标签,然后获取【src】属性内容,将base64转换成image对象,缩放图片,之后再将缩放的图片进行base64编码,重新替换【src】属性。
具体上面的代码已经实现了,可以仔细看下。
注意:这种图片导出有一个缺点,就是导出的图片可能会变形,无法控制宽高比。
以上,就是使用Java + POI + Jsoup实现富文本内容导出到word文档的操作步骤。
【操作word】Java + POI导出富文本的内容到word文档相关推荐
- Java poi导出带html标签内容的word文档
public static void exportWord(HttpServletResponse response, String content, String fileName) throws ...
- java freemarker 导出富文本到Word文档
最近一直在加班 导致看到代码就想吐 今天抽出时间来记录一下 用freemaker导出富文本信息 之前使用freemaker导出图片等信息时 使用的是xml方式,不明白的 可以看 freemaker生成 ...
- springboot导出富文本框数据到word
这里需要注意的是:依赖的版本号都是一一对应的,如果使用不兼容的版本号,可能会报编译异常和缺少类的错误,这里已提供对应的所需依赖和版本号,大家可以参考一下. 具体的api文档可以参考官网api,很好理解 ...
- Java POI导出(图片,文字,表格)word文档
先给出官网链接,方便各位博友深入了解 http://deepoove.com/poi-tl/ 这里的教程,针对导出带有图片.文字.表格的Word文档 1.话不多说 先添加依赖 <dependen ...
- java导出富文本到word_富文本编辑器内容实现word导出下载,请各位大神们指点,感激不尽...
展开全部 给个我之前的写的例子给你action 层public ActionForward dataExport(ActionMapping mapping, ActionForm form, Htt ...
- java 富文本 word_Java导出富文本到word
源码地址: 背景 最近用java开发一个中车项目管理系统,里面有一个维修单word导出功能. 可用方案 在网上查找资料,总结出两种比较可行的方案. (1) 制作word模板,导出成mht文件(单页面网 ...
- Java 实现HTML富文本导出至word完美解决方案
Java 实现HTML富文本导出至word完美解决方案 **需求: 最近用java开发一个申报管理系统,里面有一个根据申请书的模板填写项目申报信息的功能,并将项目申请书word导出功能.** 1: 动 ...
- java根据html生成word文档,Java之HTML富文本导出WORD(不含图片)
一.需求: 我们在使用富文本编辑器来编辑文本的时候,文本会自带HTML的标签比如 等来修饰字体样式. 比如ueditor.kindeditor等富文本编辑器. 那么,我们如何将富文本编辑器里的内容导出 ...
- Java POI导出word文件及生成表格
HWPF是处理 Microsoft Word 97(-2007) .doc文件格式,它还为较旧的Word 6和Word 95文件格式提供了有限的只读支持.包含在poi-scratchpad-XXX.j ...
最新文章
- win10 安装字体且不占用系统盘资源
- easyui 传递参数报错(错误:uncaught SyntaxError: Unexpected identifier)
- Flex Builder 2 注册码
- 阿里云峰会 | 统一召回引擎在搜索场景的应用实践
- 我通过“种树”,拿下鹅厂实习offer
- 引脚悬空是什么电平_STM32单片机必须掌握的八种IO口模式和引脚配置方式
- 如何用DOM4J编程使用xml schema
- Java 学习笔记(官方不推荐写法篇)
- 中国高铁走向全球,一个行业标准帮了大忙
- 多频电磁感应仪GEM-2介绍
- Sql Prompt使用技巧
- idea 关闭检查更新_intellij idea怎么关闭自动更新
- shopex mysql索引_shopex数据库表结构说明文档.doc
- 中标麒麟Linux64平台上QT5.6.3源码编译安装
- 计算机图形学迷宫论文,三维迷宫的设计与制造
- 三维激光扫描系统基本原理及分类
- EPICS stream模块使用示例 -- 基于字符串协议的通信
- IB学生喜欢申请哪些英国院校?
- 拿两千块钱的薪水要有一万块钱的范儿--蜗居编剧
- 【小知识】有趣代码注释图案【持续收集更新...】
热门文章
- 几个手机兼职做任务发布悬赏的app对比
- 科大讯飞的2022:夯实“根据地”业务,以技术创新点燃大模型产业落地的“星星之火”...
- 两个狮子和老鼠的小故事
- win10设置各种闪退解决办法
- 不是所有人都适合职场
- 同源时钟、同相位时钟、同时钟域时钟
- 九号机器人田奇峰_九号机器人三款新品亮相 以全新视角解读服务机器人产业...
- 数据库系统原理与应用教程(052)—— MySQL 的数据完整性(十四):交叉表查询(行列转换)
- macOS无法退出登录,显示关闭所有icloud服务再试一次
- 百度地图、高德地图都用POI吸引你,不过它到底是什么?