Java POI导出富文本的内容到word文档

这篇具有很好参考价值的文章主要介绍了Java POI导出富文本的内容到word文档。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、需求:

当创建使用富文本编辑器,操作完的数据,传输到后台都是带有html标签的。

如:<h1>标题头</h1><h2>第二个标题</h2><a href="www.baidu.com">百度搜索</a>

我们想把富文本数据转换为Word内容。

二,依赖

<!-- 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>

三、解决方案

Word是完全支持html标签的,但是我们获取到的富文本内容并不是完整的html代码,所有我们需要先补全html标签,然后转码,然后输出。文章来源地址https://www.toymoban.com/news/detail-707603.html

1,接口类

package com.zl.exportword;

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.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lei
 * @version 1.0
 * @date 2022/11/14 10:25
 */
@RestController
@RequestMapping("/export")
public class ExportController {

    @RequestMapping(value = "/exportWord")
    public void export(HttpServletRequest request, HttpServletResponse response) throws Exception {
        try {
            String tmpContent = "<h1>如何将富文本内容导出到word文档</h1><p style=\"color:red;font-size:20px;\">采用poi将富文本内容导出到word文档</p><div style=\"background-color:green;\">这是有背景颜色的div内容</div>\n" +
                    "<img src=\"这里写base64后的图片编码\">这是base64编码后的图片";

            // 获取img图片标签
            // 1.Jsoup解析html
            Document 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编码后替换到富文本内容里面导出word
            index = 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();
                        // 如果图片宽度大于650,图片缩放
                        //System.out.println("----"+width+"-----"+height);
                        if (width > 650) {
                            //高度等比缩放
                            height = (int)(height*650.0/width);
                            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();
        }
    }


    /**
     * 倒入本地测试
     * @throws Exception
     */
    @RequestMapping(value = "/export")
    public void export() throws Exception {
        try {
            StringBuilder sb = new StringBuilder("<h1>如何将富文本内容导出到word文档</h1><p style=\"color:red;font-size:20px;\">采用poi将富文本内容导出到word文档</p><div style=\"background-color:green;\">这是有背景颜色的div内容</div>\n" +
                    "<img src=\"").append("");
       //提前转换过base64编码的图片,由于编码文本太长,我提前存储到txt中,再通过io流读取出来
            File file = new File("/Users/lei/base.txt");
            FileInputStream fileInputStream = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(fileInputStream);
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len=bis.read(bytes))!=-1){
                sb.append(new String(bytes, 0, len));
            }


            sb.append("\">这是base64编码后的图片");
            String tmpContent = sb.toString();

            // 获取img图片标签
            // 1.Jsoup解析html
            Document document = Jsoup.parse(tmpContent);
            // 获取所有img图片标签
            Elements imgs = document.getElementsByTag("img");
            int index = 0;
            List<String> imgBase64List = new ArrayList<>();
            for (Element element : imgs) {
                imgBase64List.add(element.attr("src"));
                // 处理特殊符号
                String attrData = element.attr("src");
                // base64编码后可能包含 + 特殊字符,所以需要转义
                attrData = attrData.replaceAll("\\+", "\\\\+");
                tmpContent = tmpContent.replaceAll(attrData, "{{image_src" + index + "}}");
                index++;
            }
            // 缩放图片大小,然后重新base64编码后替换到富文本内容里面导出word
            index = 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();
                        // 如果图片宽度大于650,图片缩放
                        System.out.println("----"+width+"-----"+height);
                        if (width > 650) {
                            //高度等比缩放
                            height = (int)(height*650.0/width);
                            BufferedImage imgZoom = ImageUtils.resizeImage(bufferedImage, 650, 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("/Users/lei/", tmpContent, "富文本内容导出word.docx");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

2,工具类

package com.zl.exportword;

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;
import java.io.File;
import java.io.FileOutputStream;


/**
 * poi操作word工具类
 * @author lei
 * @version 1.0
 * @date 2022/11/14 10:23
 */
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 {
        //图片转为base64方法
        //String imagebase64 = getImageStr(imagePath); 
        // 拼接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();
    }

    /**
     * 富文本内容到word(本地)
     * @param content 输出内容
     * @param fileName 导出文件名称
     * @throws Exception
     */
    public static void exportHtmlToWord(String filepath, 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);

        FileOutputStream out = new FileOutputStream(new File(filepath+fileName));
        poifs.writeFilesystem(out);
        bais.close();
        out.close();
    }
}
package com.zl.exportword;

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 lei
 * @date 2022/11/14 10:20
 * @version 1.0
 */
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;
    }

    //图片转化成base64字符串
    public static String getImageStr(String imgPath) throws IOException {
        File file = new File(imgPath);
        String fileContentBase64 = null;
        if(file.exists()){
            String fileType = imgPath.substring(imgPath.length()-3);
            String base64Str = "data:" + fileType + ";base64,";
            String content = null;
            //将图片文件转化为字节数组字符串,并对其进行Base64编码处理
            InputStream in = null;
            byte[] data = null;
            //读取图片字节数组
            try {
                in = new FileInputStream(file);
                data = new byte[in.available()];
                in.read(data);
                in.close();
                //对字节数组Base64编码
                if (data == null || data.length == 0) {
                    return null;
                }
                //content = Base64.encodeBytes(data);
                content = new BASE64Encoder().encode(data);
                if (content == null || "".equals(content)) {
                    return null;
                }
                // 缩小图片
                if (StringUtils.isNotBlank(content)) {
                    BufferedImage bufferedImage = ImageUtils.bytesToBufferedImage(ImageUtils.base64ToByte(content));
                    if (bufferedImage != null){
                        int height = bufferedImage.getHeight();
                        int width = bufferedImage.getWidth();
                        // 如果图片宽度大于650,图片缩放
                        if (width > 500) {
                            //高度等比缩放
                            height = (int)(height*500.0/width);
                            BufferedImage imgZoom = ImageUtils.resizeImage(bufferedImage, 500, height);
                            content = ImageUtils.imageToBase64(ImageUtils.imageToBytes(imgZoom));
                        }
                    }
                }
                fileContentBase64 = base64Str + content;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (in != null) {
                    in.close();
                }
            }
        }

        return fileContentBase64;
    }
}

到了这里,关于Java POI导出富文本的内容到word文档的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java POI导出Word、Excel、Pdf文档(可在线预览PDF)

    1、导入依赖Pom.xml        dependency             groupIdorg.apache.poi/groupId             artifactIdpoi/artifactId             version3.14/version         /dependency 2、Controller   3、Service a、pdfService b、wordService c、excelService  4、Utils 5、模板截图   6、前端

    2024年02月08日
    浏览(34)
  • Java poi之word文本替换

    应公司需求,需实现以下功能 word文本内容的替换; word文本内容的提取; word文档中图片的提取存放 此文章将使用Apache POI实现Word文档中文本内容的替换更新; Apache POI 是基于 Office Open XML 标准(OOXML)和 Microsoft 的 OLE 2 复合文档格式(OLE2)处理各种文件格式的开源项目。 简

    2024年02月07日
    浏览(30)
  • java使用apache.poi导出word文件

    功能说明: 将试卷导出word,并可以打印,装订,效果图: 下面是实现代码:

    2024年02月15日
    浏览(34)
  • 【Java Easypoi & Apache poi】 Word导入与导出

            如果这里造成了读取resources下的文件返回前端乱码问题:除了HttpServletResponse响应中设置字体问题,还有可能是因为在编译期文件就已经乱码了,所以需要在pom.xml中增加以下配置。

    2024年02月10日
    浏览(46)
  • 【Easypoi & Apache poi】 Java后端 Word导入与导出

            如果这里造成了读取resources下的文件返回前端乱码问题:除了HttpServletResponse响应中设置字体问题,还有可能是因为在编译期文件就已经乱码了,所以需要在pom.xml中增加以下配置。

    2024年02月11日
    浏览(38)
  • Java poi之Excel文本图片内容提取

    应公司需求,需实现以下功能 Excel文本内容的替换; Excel文本内容的提取; Excel中图片的提取存放 此文章将使用Apache POI实现Excel文件中文本内容及图片的提取; Apache POI 是基于 Office Open XML 标准(OOXML)和 Microsoft 的 OLE 2 复合文档格式(OLE2)处理各种文件格式的开源项目。

    2024年02月05日
    浏览(69)
  • java 导出word,java根据提供word模板导出word文档

    本文主要讲解,利用poi-tl在word中动态生成表格行,进行文字、图片填充。一共提供了两种方式,1.基于本地文件 2.基于网络文件 本文讲解思路,1.先看示例,2. 示例对应的代码展示 3. 基本概念讲解(api自行查阅文档)。 这样便于快速展示,不符合你的业务需求的可以直接划走

    2024年02月14日
    浏览(31)
  • java使用poi-tl导出word及转换PDF后的合并导出pdf

    为某单位开发的一款项目申报审批系统,用户需求在申报阶段填写的信息资料能够导出PDF。且项目申报的报告正文为用户上传,所以需要合并导出。 在项目初期阶段使用的是PDF的预设模板导出,因为以前使用过,比较熟悉。所以优先选择此方法,但项目测试阶段发现问题,因

    2024年02月06日
    浏览(61)
  • Android 基于POI库,根据模板导出word文档

    由于项目需求,需要根据用户提供的word模板,填充动态内容生成新的word,为了记录自己的踩坑日记,记录一下。 Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对文档读和写的功能。 这里给出官网链接-POI官网,同时下载版本也在官网链接中,可

    2024年01月18日
    浏览(38)
  • java 使用POI-TL根据word模版,生成word文件,含图片,富文本。

    1.引入mavna坐标` 2 .poi-tl-ext插件主要用于富文本内容格式在word展现 3.word模版创建 3.具体代码实现 4.本文的miniourl路径实质为网络路径的文件。

    2024年02月16日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包