SpringBoot导出Word文档的三种方式

一、导出方案

.doc      application/msword
.dot application/msword .docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
.dotx application/vnd.openxmlformats-officedocument.wordprocessingml.template
.docm application/vnd.ms-word.document.macroEnabled.12
.dotm application/vnd.ms-word.template.macroEnabled.12 .xls application/vnd.ms-excel
.xlt application/vnd.ms-excel
.xla application/vnd.ms-excel .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
.xltx application/vnd.openxmlformats-officedocument.spreadsheetml.template
.xlsm application/vnd.ms-excel.sheet.macroEnabled.12
.xltm application/vnd.ms-excel.template.macroEnabled.12
.xlam application/vnd.ms-excel.addin.macroEnabled.12
.xlsb application/vnd.ms-excel.sheet.binary.macroEnabled.12 .ppt application/vnd.ms-powerpoint
.pot application/vnd.ms-powerpoint
.pps application/vnd.ms-powerpoint
.ppa application/vnd.ms-powerpoint .pptx application/vnd.openxmlformats-officedocument.presentationml.presentation
.potx application/vnd.openxmlformats-officedocument.presentationml.template
.ppsx application/vnd.openxmlformats-officedocument.presentationml.slideshow
.ppam application/vnd.ms-powerpoint.addin.macroEnabled.12
.pptm application/vnd.ms-powerpoint.presentation.macroEnabled.12
.potm application/vnd.ms-powerpoint.template.macroEnabled.12
.ppsm application/vnd.ms-powerpoint.slideshow.macroEnabled.12 .mdb application/vnd.ms-access

二、富文本转换后的HTML下载为Word文档

1、准备

  • 业务需求

    • 前端使用富文本插件生成带HTML标签的word文档,然后需要下载这个word文档。
    • 每个word文档的格式是可变的
  • 扩展业务需求:

    • 甚至可以去替换HTML的Word中的内容,然后导出需要的文档;缺点:替换字符串麻烦、而且HTML的Word的标签还需要研究。
    • 基于上述的业务需求。建议使用模板技术导出(也就是“三”)
  • 参考:

  • 导出结果

2、实现

2.1、导包

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml-schemas -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>

2.2、HTML的word文档

package com.cc.ewd.html;

/**
* @author CC
* @since 2023/4/24 0024
*/
public interface HtmlConstants { /**
* 普通文档(富文本生成的)
*/
String HTML1 = "<h1 style=\"text-align: center;\"><strong>文章标题</strong></h1><h1><strong>一、标题1" +
"</strong></h1><p><strong> &nbsp; &nbsp; &nbsp; 我是数据:{NUM}</strong></p><h2><strong>" +
"1.1、吾问无为谓</strong></h2><table style=\"width: 100%;\">" +
"<tbody><tr><th colSpan=\"1\" rowSpan=\"1\" width=\"auto\">序号</th>" +
"<th colSpan=\"1\" rowSpan=\"1\" width=\"auto\">第一列</th>" +
"<th colSpan=\"1\" rowSpan=\"1\" width=\"auto\">第二列</th>" +
"<th colSpan=\"1\" rowSpan=\"1\" width=\"auto\">第三列</th>" +
"<th colSpan=\"1\" rowSpan=\"1\" width=\"auto\">第四列</th>" +
"</tr><tr><td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">1</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">11</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">22</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">33</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">44</td>" +
"</tr><tr><td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">2</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">11</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">22</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">33</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">44</td>" +
"</tr><tr><td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">3</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">11</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">22</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">33</td>" +
"<td colspan=\"1\" rowspan=\"1\" width=\"auto\" style=\"text-align: center;\">44</td></tr>" +
"</tbody></table><p><br></p>"; /**
* 带表格文档(可以富文本生成,也可以使用word文档另存为HTML文件,然后拷出来)
*/
String HTML2 = "<!--StartFragment--><div class=\"Section0\" style=\"layout-grid:15.6000pt;\" ><h1 align=center style=\"text-align:center;\" ><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;\n" +
"font-size:22.0000pt;mso-font-kerning:22.0000pt;\" ><font face=\"宋体\" >标题</font></span></b><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;\n" +
"font-size:22.0000pt;mso-font-kerning:22.0000pt;\" ><o:p></o:p></span></b></h1><h2><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:黑体;mso-ascii-font-family:Arial;\n" +
"mso-hansi-font-family:Arial;mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;\n" +
"font-size:16.0000pt;mso-font-kerning:1.0000pt;\" ><font face=\"黑体\" >一、段落</font><font face=\"Arial\" >1</font></span></b><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:Arial;mso-fareast-font-family:黑体;\n" +
"mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;font-size:16.0000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></b></h2><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >哒哒</font></span><b><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';color:rgb(0,0,255);\n" +
"font-weight:bold;font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >哒哒哒</font></span></b><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >哒</font></span><span style=\"mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p><h3><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;\n" +
"font-size:16.0000pt;mso-font-kerning:1.0000pt;\" ><font face=\"Calibri\" >1.1</font><font face=\"宋体\" >、表格</font></span></b><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;\n" +
"mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;font-size:16.0000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></b></h3><table class=MsoTableGrid border=1 cellspacing=0 style=\"border-collapse:collapse;border:none;mso-border-left-alt:0.5000pt solid windowtext;\n" +
"mso-border-top-alt:0.5000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;mso-border-bottom-alt:0.5000pt solid windowtext;\n" +
"mso-border-insideh:0.5000pt solid windowtext;mso-border-insidev:0.5000pt solid windowtext;mso-padding-alt:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;\" ><tr><td width=142 valign=center style=\"width:106.5000pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >序号</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td><td width=142 valign=center style=\"width:106.5000pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >列</font><font face=\"Calibri\" >1</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td><td width=142 valign=center style=\"width:106.5500pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >列</font><font face=\"Calibri\" >2</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td><td width=142 valign=center style=\"width:106.5500pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:1.0000pt solid windowtext;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"宋体\" >列</font><font face=\"Calibri\" >3</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td></tr><tr><td width=142 valign=center style=\"width:106.5000pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"Calibri\" >1</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td><td width=142 valign=center style=\"width:106.5000pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"Calibri\" >11</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td><td width=142 valign=center style=\"width:106.5500pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"Calibri\" >22</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td><td width=142 valign=center style=\"width:106.5500pt;padding:0.0000pt 5.4000pt 0.0000pt 5.4000pt ;border-left:1.0000pt solid windowtext;\n" +
"mso-border-left-alt:0.5000pt solid windowtext;border-right:1.0000pt solid windowtext;mso-border-right-alt:0.5000pt solid windowtext;\n" +
"border-top:none;mso-border-top-alt:0.5000pt solid windowtext;border-bottom:1.0000pt solid windowtext;\n" +
"mso-border-bottom-alt:0.5000pt solid windowtext;\" ><p class=MsoNormal align=center style=\"text-align:center;\" ><span style=\"font-family:宋体;mso-ascii-font-family:Calibri;mso-hansi-font-family:Calibri;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><font face=\"Calibri\" >33</font></span><span style=\"font-family:Calibri;mso-fareast-font-family:宋体;mso-bidi-font-family:'Times New Roman';\n" +
"font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></p></td></tr></table><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:Calibri;mso-fareast-font-family:宋体;\n" +
"mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;mso-font-kerning:1.0000pt;\" ><o:p>&nbsp;</o:p></span></p><h2><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:黑体;mso-ascii-font-family:Arial;\n" +
"mso-hansi-font-family:Arial;mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;\n" +
"font-size:16.0000pt;mso-font-kerning:1.0000pt;\" ><font face=\"黑体\" >二、段落</font><font face=\"Arial\" >2</font></span></b><b style=\"mso-bidi-font-weight:normal\" ><span style=\"mso-spacerun:'yes';font-family:Arial;mso-fareast-font-family:黑体;\n" +
"mso-bidi-font-family:'Times New Roman';mso-ansi-font-weight:bold;font-size:16.0000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><o:p></o:p></span></b></h2><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><o:p>&nbsp;</o:p></span></p><p class=MsoNormal ><span style=\"mso-spacerun:'yes';font-family:宋体;mso-ascii-font-family:Calibri;\n" +
"mso-hansi-font-family:Calibri;mso-bidi-font-family:'Times New Roman';font-size:10.5000pt;\n" +
"mso-font-kerning:1.0000pt;\" ><o:p>&nbsp;</o:p></span></p></div><!--EndFragment-->"; }

2.3、导出

  • 逻辑、注意事项看注释

  • 代码:

package com.cc.ewd.web.controller;

import com.cc.ewd.html.HtmlConstants;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; /** 业务需求:前端使用富文本插件生成带HTML标签的word文档,然后需要下载这个word文档。
* @author CC
* @since 2023/4/24 0024
*/
@RestController
@RequestMapping("/apachePoiExport")
public class ApachePoiExport { /** 将HTML内容(富文本生成的HTML)转换为Word文档并下载
* @param response HTTP响应
*/
@GetMapping
public void getDoc(HttpServletResponse response) {
String fileName = "Word文件名";
String html = HtmlConstants.HTML2;
//导出word的方法
exportWord(fileName, html, response);
} /** <p>将HTML内容(富文本生成的HTML)转换为Word文档并下载(word2007之后的_docx)</p>
* <li>参考:https://my.oschina.net/u/1045509/blog/1924024</li>
* <li>参考:https://blog.csdn.net/qq_42682745/article/details/120867432</li>
* @param fileName 文件名
* @param html 富文本生成的HTML
* @param response 响应
* @since 2023/4/25 0025
* @author CC
**/
public static void exportWord(String fileName, String html, HttpServletResponse response) {
//0、获取富文本的html:
// HTML内容必须被<html><body></body></html>包装;最好设置一下编码格式
// HTML在这里设置<head></head>是为了让输入的文档是以"页面视图"。而不是"Web版式"
String wrappedHtml =
"<html xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"\n" +
"xmlns:w=\"urn:schemas-microsoft-com:office:word\" xmlns:m=\"http://schemas.microsoft.com/office/2004/12/omml\"\n" +
"xmlns=\"http://www.w3.org/TR/REC-html40\">" +
"<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>" +
"<body>%s</body>" +
"</html>"; wrappedHtml = String.format(wrappedHtml, html); //1、将HTML转换为Word文档byte数组
byte[] bytes = wrappedHtml.getBytes(StandardCharsets.UTF_8);
try (POIFSFileSystem poifsFileSystem = new POIFSFileSystem();
InputStream byteInputStream = new ByteArrayInputStream(bytes);
// InputStream inputStream = new BufferedInputStream(byteInputStream);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
){
//2、使用ApachePoi转换word并设置到输出流outputStream
DirectoryEntry directory = poifsFileSystem.getRoot();
//WordDocument名称不允许修改
directory.createDocument("WordDocument", byteInputStream);
//将Word文档写入POIFSFileSystem对象
poifsFileSystem.writeFilesystem(outputStream); //3、①将Word文档(输出流outputStream)写入HTTP响应并下载;②也可以上传到自己的文件服务器然后返回URL给前端下载。
response.setCharacterEncoding("utf-8");
//设置content-type就是告诉浏览器这是啥玩意儿
//"octet-stream" :通用二进制流;
//"msword" :Microsoft Word文档
//"vnd.openxmlformats-officedocument.wordprocessingml.document" :响应的内容类型设置为Microsoft Word 2007及更高版本的docx格式。对应的文件名后缀需要改成”docx“
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8");
//解决跨域不显示在header里面的问题
response.setHeader("Access-Control-Expose-Headers","Content-disposition");
//"attachment":让浏览器把响应视为附件并下载
//"inline": 让浏览器打开Word文档而不是下载它
response.setHeader("Content-disposition","attachment; filename=" +
URLEncoder.encode(fileName.concat(".docx"), "UTF-8"));
//BufferedOutputStream缓冲流:可以将数据缓存在内存中,以减少对底层IO的调用次数,从而提高性能。
//ServletOutputStream:用于向客户端发送数据的
//因为需要将数据写入HTTP响应,所以使用ServletOutputStream是更好的选择。
OutputStream out = new BufferedOutputStream(response.getOutputStream());
out.write(outputStream.toByteArray());
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
} }

三、使用模板技术导出

  • 使用Thymeleaf模板技术(推荐,也是我使用的)。也可以使用FreeMarker

  • Word文件的格式是固定

  • 可以根据需求写入不同的数据

1、准备工作

1.1、导包

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

1.2、导出文件的预处理,Thymeleaf语法

  • 使用WPS(建议使用微软的Word)新建一个需要导出Word文件

  • 这个Word文件中,需要替换的值,最好使用单独的格式。因为单独的格式在HTML或者xml中才能区分

  • 弄好Word文件,最后另存为xml格式或者HTML(单个文件)格式。就得到我们需要的xml或者HTML格式的Word文件。

  • 使用Thymeleaf语法修改xml文件

    • 参考:Thymeleaf更多语法见下面:

      https://blog.csdn.net/weixin_45203607/article/details/120251923
      
      https://blog.csdn.net/guoqigengxin/article/details/108674177普通文本
    • 普通文本

  • 循环

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  • 条件判断:if-else

1.3、把处理好的xml文件放到resources下

1.4、使用HTML的注意事项

  • 见附件:thymeleaf_3_wps.html

  • 另存为后,修改HTML的编码格式:utf-8

  • 设置值,直接可以设置在:font 标签上

  • “页面视图“修改:

    • 参考导出页面视图见:一、导出方案


2、原理

  • 可以使用xml导出、也可以使用HTML导出。
  • 导出前需要预处理xml
  • 可以使用下面的进行测试、导出。

2.1、原理

package com.cc.ewd.web.controller;

import com.cc.ewd.vo.Msg4Vo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /** thymeleaf导出的原理
* @author CC
* @since 2023/4/25 0025
*/
@RestController
@RequestMapping("/thymeleafTheoryExport")
public class ThymeleafTheoryExport { @Resource
private SpringTemplateEngine springTemplateEngine; /** <p>原理</p>
* <ol>
* <li>相当于把word文件转为xml或者html,然后修改其中的值再以xml、html下载成word文件</li>
* <li>这个方法只能运行一次,因为对ClassLoaderTemplateResolver的设置是一次性的</li>
* <li>所以需要将ClassLoaderTemplateResolver设置成单例:配置Bean。</li>
* <li>doc或docx的模板别使用WPS的文档,使用微软的office新建word文档,然后转为xml或html</li>
* <li>可以导出xml、也可以导出html:建议使用xml</li>
* </ol>
*/
@GetMapping
public void thymeleafExport(HttpServletResponse response){
String fileName = "第一个thy的文件"; //一、设置Thymeleaf模板
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
//xml文件地址:自定义xml的文件夹:thymeleafcs/thymeleaf_1_wps.xml
//xml文件地址:默认放在thymeleaf下就可以读取到
templateResolver.setPrefix("thymeleafcs/");
//设置文件的后缀
templateResolver.setSuffix(".xml");
// templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("utf-8");
//模板模式:默认是HTML。改为xml
// templateResolver.setTemplateMode(TemplateMode.XML);
templateResolver.setTemplateMode(TemplateMode.HTML);
//加载模板
springTemplateEngine.setTemplateResolver(templateResolver);
//启用Spring EL编译器
springTemplateEngine.setEnableSpringELCompiler(true); //二、设置数据(可以用map,也可以用对象)
Map<String,Object> map = new HashMap<>();
//1普通文本参数
map.put("msg1","我是参数1111");
map.put("msg2","我是参数2222");
map.put("msg3","我是参数3333");
//2if-else参数
map.put("thIf1","1");
map.put("thIf2","2"); //3循环:构建集合参数,用于表格:可以是Map;可以是对象
// List<Map<String,Object>> msg4Vos = new ArrayList<>();
List<Msg4Vo> msg4Vos = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//1map方式
// Map<String,Object> map4 = new HashMap<>();
// map4.put("l1","列1-" + i);
// map4.put("l2","列2-" + i);
// map4.put("l3","列3-" + i);
// map4.put("l4","列4-" + i);
// msg4Vos.add(map4);
//2对象方式
Msg4Vo vo = new Msg4Vo();
vo.setL1("列1-" + i);
vo.setL2("列2-" + i);
vo.setL3("列3-" + i);
vo.setL4("列4-" + i);
msg4Vos.add(vo);
}
map.put("msg4Vos",msg4Vos); //4设置数据
Context context = new Context();
context.setVariables(map);
//写入输入(模板名称,数据)
String process = springTemplateEngine.process("thymeleaf_4_wps_final", context); //三、下载
//建议下载成doc的。不然微软的office可能打不开
try {
byte[] bytes = process.getBytes(StandardCharsets.UTF_8);
// ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
// ByteArrayOutputStream outputStream = getByteArrayOutputStream(inputStream); response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.setHeader("Access-Control-Expose-Headers","Content-disposition");
response.setHeader("Content-disposition","attachment; filename=" +
URLEncoder.encode(fileName.concat(".doc"), "UTF-8"));
ServletOutputStream out = response.getOutputStream(); //两种方式都可以:用bytes好些
// out.write(outputStream.toByteArray());
out.write(bytes);
out.flush();
out.close();
}catch(Exception e){
e.printStackTrace();
} } /** 将 ByteArrayInputStream 拷贝成 ByteArrayOutputStream
* 将 字节数组输入流 拷贝成 字节数组输出流
*/
public static ByteArrayOutputStream getByteArrayOutputStream(ByteArrayInputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
return outputStream;
} }

2.2、导出后预览

3、实现

3.1、yml配置

server:
port: 5555 spring:
#thymeleaf的配置
thymeleaf:
#关闭 Thymeleaf 的缓存开发过程中无需重启
#Thymeleaf默认会开启页面缓存,提高页面并发能力。但会导致我们修改页面不会立即被展现,因此我们关闭缓存
cache: false
#设置thymeleaf页面的编码
encoding: UTF-8
#模型:XML/HTML5:HTML是默认值, 为了清楚起见, 在此处添加。
mode: XML
#设置thymeleaf页面的后缀:.html是默认。
suffix: .xml
#设置thymeleaf页面的存储路径
prefix: classpath:/thymeleafcs/
#使用Spring 4.2.4或更高版本启用SpringEL编译器
#可以加快大多数情况下的执行速度, 但是当一个模板中
#的表达式在不同数据类型之间重用时,
#可能与特定情况不兼容, 因此该标志默认为“false”
#以实现更安全的向后兼容性。
enable-spring-el-compiler: true

3.2、实现

package com.cc.ewd.web.controller;

import com.cc.ewd.vo.Msg4Vo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine; import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /** thymeleaf导出的实现
* @author CC
* @since 2023/5/4 0025
*/
@RestController
@RequestMapping("/thymeleafExport")
public class ThymeleafExport { @Resource
private SpringTemplateEngine springTemplateEngine; /** <p>原理</p>
* <ol>
* <li>相当于把word文件转为xml或者html,然后修改其中的值再以xml、html下载成word文件</li>
* <li>这个方法只能运行一次,因为对ClassLoaderTemplateResolver的设置是一次性的</li>
* <li>所以需要将ClassLoaderTemplateResolver设置成单例:配置Bean。</li>
* <li>doc或docx的模板别使用WPS的文档,使用微软的office新建word文档,然后转为xml或html</li>
* <li>可以导出xml、也可以导出html:建议使用xml</li>
* </ol>
*/
@GetMapping
public void thymeleafExport(HttpServletResponse response){
String fileName = "第二个thy的文件"; //一、设置数据(可以用map,也可以用对象)
Map<String,Object> map = new HashMap<>();
//1普通文本参数
map.put("msg1","我是参数1111");
map.put("msg2","我是参数2222");
map.put("msg3","我是参数3333");
//2if-else参数
map.put("thIf1","1");
map.put("thIf2","2"); //3循环:构建集合参数,用于表格:可以是Map;可以是对象
// List<Map<String,Object>> msg4Vos = new ArrayList<>();
List<Msg4Vo> msg4Vos = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//1map方式
// Map<String,Object> map4 = new HashMap<>();
// map4.put("l1","列1-" + i);
// map4.put("l2","列2-" + i);
// map4.put("l3","列3-" + i);
// map4.put("l4","列4-" + i);
// msg4Vos.add(map4);
//2对象方式
Msg4Vo vo = new Msg4Vo();
vo.setL1("列1-" + i);
vo.setL2("列2-" + i);
vo.setL3("列3-" + i);
vo.setL4("列4-" + i);
msg4Vos.add(vo);
}
map.put("msg4Vos",msg4Vos); //4设置数据
Context context = new Context();
context.setVariables(map);
//写入输入(模板名称,数据)
String process = springTemplateEngine.process("thymeleaf_4_wps_final", context); //二、下载
//建议下载成doc的。不然微软的office可能打不开
try {
byte[] bytes = process.getBytes(StandardCharsets.UTF_8);
// ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
// ByteArrayOutputStream outputStream = getByteArrayOutputStream(inputStream); response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.setHeader("Access-Control-Expose-Headers","Content-disposition");
response.setHeader("Content-disposition","attachment; filename=" +
URLEncoder.encode(fileName.concat(".doc"), "UTF-8"));
ServletOutputStream out = response.getOutputStream(); //两种方式都可以:用bytes好些
// out.write(outputStream.toByteArray());
out.write(bytes);
out.flush();
out.close();
}catch(Exception e){
e.printStackTrace();
} } /** 将 ByteArrayInputStream 拷贝成 ByteArrayOutputStream
* 将 字节数组输入流 拷贝成 字节数组输出流
*/
public static ByteArrayOutputStream getByteArrayOutputStream(ByteArrayInputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
return outputStream;
} }

3.3、不使用yml配置,使用配置bean方式

  • 可以配置不同的bean,注入使用的时候,使用我们需要的bean。实现动态使用不同类型的模板的功能。
  • 如果yml中配置了, 又配置了bean。yml中的配置会失效。
  • 其中一个bean一定要添加:@Primary。来设置默认的bean
  • config配置
package com.cc.ewd.config;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templatemode.TemplateMode; import javax.annotation.Resource; /** ThymeLeaf单独的配置
* @since 2023/5/4 0004
* @author CC
**/
@Configuration
public class MyThymeLeafConfig { @Resource
private ApplicationContext applicationContext; /** 自定义的bean
* @return SpringTemplateEngine
* @Primary :<li>作用:指定使用名为“myTemplateEngine”的bean作为默认bean。</li>
* <li>这样,当您在需要使用SpringTemplateEngine的地方没有指定@Qualifier注释时,Spring将使用该默认bean。</li>
* <li>使用@Resource时,可直接设置名字。不用使用@Qualifier注释</li>
*/
@Bean(name = "myTemplateEngine")
@Primary
public SpringTemplateEngine myTemplateEngine(){
// SpringTemplateEngine自动应用SpringStandardDialect
// 并启用Spring自己的MessageSource消息解析机制。
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
SpringResourceTemplateResolver templateResolver = myTemplateResolver();
templateEngine.setTemplateResolver(templateResolver);
// 使用Spring 4.2.4或更高版本启用SpringEL编译器
// 可以加快大多数情况下的执行速度, 但是当一个模板中
// 的表达式在不同数据类型之间重用时,
// 可能与特定情况不兼容, 因此该标志默认为“false”
// 以实现更安全的向后兼容性。
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
} /** 自定义配置
* @return SpringResourceTemplateResolver
*/
@Bean("myTemplateResolver")
public SpringResourceTemplateResolver myTemplateResolver(){
// SpringResourceTemplateResolver自动与Spring自己集成
// 资源解决基础设施, 强烈推荐。
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("classpath:thymeleafcs/");
templateResolver.setSuffix(".html");
templateResolver.setCharacterEncoding("UTF-8");
// HTML是默认值, 为了清楚起见, 在此处添加。
templateResolver.setTemplateMode(TemplateMode.HTML);
return templateResolver;
} //---------------------------------------------- /** 自定义的bean2
* @return SpringTemplateEngine
*/
@Bean(name = "myTemplateEngine2")
public SpringTemplateEngine myTemplateEngine2(){
// SpringTemplateEngine自动应用SpringStandardDialect
// 并启用Spring自己的MessageSource消息解析机制。
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
SpringResourceTemplateResolver templateResolver = myTemplateResolver2();
templateEngine.setTemplateResolver(templateResolver);
// 使用Spring 4.2.4或更高版本启用SpringEL编译器
// 可以加快大多数情况下的执行速度, 但是当一个模板中
// 的表达式在不同数据类型之间重用时,
// 可能与特定情况不兼容, 因此该标志默认为“false”
// 以实现更安全的向后兼容性。
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
} /** 自定义配置2
* @return SpringResourceTemplateResolver
*/
@Bean("myTemplateResolver2")
public SpringResourceTemplateResolver myTemplateResolver2(){
// SpringResourceTemplateResolver自动与Spring自己集成
// 资源解决基础设施, 强烈推荐。
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("classpath:thymeleafcs/");
templateResolver.setSuffix(".xml");
templateResolver.setCharacterEncoding("UTF-8");
// HTML是默认值, 为了清楚起见, 在此处添加。
templateResolver.setTemplateMode(TemplateMode.XML);
return templateResolver;
} }
  • 使用

    • @Resource注入:

          @Resource(name = "myTemplateEngine")
      private SpringTemplateEngine springTemplateEngine;
    • @Autowired注入:

          @Autowired
      @Qualifier("myTemplateEngine")
      private SpringTemplateEngine springTemplateEngine1Html;
    • 配置文件会失效——配置类优先

    • 使用:根据传入的type不同。使用的模板是不同的。

package com.cc.ewd.web.controller;

import com.cc.ewd.vo.Msg4Vo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine; import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /** thymeleaf导出的实现
* @author CC
* @since 2023/5/4 0025
*/
@RestController
@RequestMapping("/thymeleafExport")
public class ThymeleafExport { // @Resource
// private SpringTemplateEngine springTemplateEngine;
@Resource(name = "myTemplateEngine")
private SpringTemplateEngine springTemplateEngine1Html;
@Resource(name = "myTemplateEngine2")
private SpringTemplateEngine springTemplateEngine2Xml; /** <p>原理</p>
* <ol>
* <li>相当于把word文件转为xml或者html,然后修改其中的值再以xml、html下载成word文件</li>
* <li>这个方法只能运行一次,因为对ClassLoaderTemplateResolver的设置是一次性的</li>
* <li>所以需要将ClassLoaderTemplateResolver设置成单例:配置Bean。</li>
* <li>doc或docx的模板别使用WPS的文档,使用微软的office新建word文档,然后转为xml或html</li>
* <li>可以导出xml、也可以导出html:建议使用xml</li>
* </ol>
*/
@GetMapping
public void thymeleafExport(@RequestParam String type, HttpServletResponse response){
String fileName = "第二个thy的文件"; //一、设置数据(可以用map,也可以用对象)
Map<String,Object> map = new HashMap<>();
//1普通文本参数
map.put("msg1","我是参数1111");
map.put("msg2","我是参数2222");
map.put("msg3","我是参数3333");
//2if-else参数
map.put("thIf1","1");
map.put("thIf2","2"); //3循环:构建集合参数,用于表格:可以是Map;可以是对象
// List<Map<String,Object>> msg4Vos = new ArrayList<>();
List<Msg4Vo> msg4Vos = new ArrayList<>();
for (int i = 0; i < 10; i++) {
//1map方式
// Map<String,Object> map4 = new HashMap<>();
// map4.put("l1","列1-" + i);
// map4.put("l2","列2-" + i);
// map4.put("l3","列3-" + i);
// map4.put("l4","列4-" + i);
// msg4Vos.add(map4);
//2对象方式
Msg4Vo vo = new Msg4Vo();
vo.setL1("列1-" + i);
vo.setL2("列2-" + i);
vo.setL3("列3-" + i);
vo.setL4("列4-" + i);
msg4Vos.add(vo);
}
map.put("msg4Vos",msg4Vos); //4设置数据
Context context = new Context();
context.setVariables(map);
//写入输入(模板名称,数据):1:html;2:xml
String process = "";
if ("1".equals(type)){
process = springTemplateEngine1Html.process("thymeleaf_3_wps", context);
}else if ("2".equals(type)){
process = springTemplateEngine2Xml.process("thymeleaf_4_wps_final", context);
} //二、下载
//建议下载成doc的。不然微软的office可能打不开
try {
byte[] bytes = process.getBytes(StandardCharsets.UTF_8);
// ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
// ByteArrayOutputStream outputStream = getByteArrayOutputStream(inputStream); response.setCharacterEncoding("utf-8");
response.setContentType("application/msword");
response.setHeader("Access-Control-Expose-Headers","Content-disposition");
response.setHeader("Content-disposition","attachment; filename=" +
URLEncoder.encode(fileName.concat(".doc"), "UTF-8"));
ServletOutputStream out = response.getOutputStream(); //两种方式都可以:用bytes好些
// out.write(outputStream.toByteArray());
out.write(bytes);
out.flush();
out.close();
}catch(Exception e){
e.printStackTrace();
} } /** 将 ByteArrayInputStream 拷贝成 ByteArrayOutputStream
* 将 字节数组输入流 拷贝成 字节数组输出流
*/
public static ByteArrayOutputStream getByteArrayOutputStream(ByteArrayInputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, length);
}
return outputStream;
} }

四、总结

  • 甚至可以结合Thymeleaf模板技术和ApachePoi技术。
  • 先使用Thymeleaf模板技术替换Word文档中的值。然后得到完整的HTML格式的Word文档
  • 然后使用ApachePoi导出HTML格式的Word文档
  • 文中使用到的文档:

https://files.cnblogs.com/files/blogs/787464/SpringBoot导出Word文档的三种方式-文档.rar?t=1683184411&download=true

SpringBoot导出Word文档的三种方式的更多相关文章

  1. 将html转换为word文档的几种方式

    1 基于wps直接将页面信息下载成word文档 public void test() { WPS.Application wps = null; try { wps = new WPS.Applica ...

  2. PHP生成word文档的三种实现方式

    PHP生成word原理 利用windows下面的 com组件 利用PHP将内容写入doc文件之中 具体实现: 利用windows下面的 com组件 原理:com作为PHP的一个扩展类,安装过offic ...

  3. 【Java】导出word文档之freemarker导出

    Java导出word文档有很多种方式,本例介绍freemarker导出,根据现有的word模板进行导出 一.简单导出(不含循环导出) 1.新建一个word文件.如下图: 2.使用word将文件另存为x ...

  4. C#导出Word文档开源组件DocX

    1.帮助文档,这东西找了很久,而且它版本很旧,还是英文,W8.1系统上打不开 http://download.csdn.net/detail/zuofangyouyuan/7673573 2.开源网址 ...

  5. freemarker导出word文档——WordXML格式解析

    前不久,公司一个项目需要实现导出文档的功能,之前是一个同事在做,做了3个星期,终于完成了,但是在项目上线之后却发现导出的文档有问题,此时,这个同事已经离职,我自然成为接班者,要把导出功能实现,但是我看 ...

  6. Java使用freemarker导出word文档

    通过freemarker,以及JAVA,导出word文档. 共分为三步: 第一步:创建模板文件 第二步:通过JAVA创建返回值. 第三步:执行 分别介绍如下: 第一步: 首先创建word文档,按照想要 ...

  7. MindManager导出Word文档功能介绍

    Mindmanager思维导图软件作为一款能与Microsoft office软件无缝集成的思维导图软件,支持Word文档的快速导入与导出,并支持Word文档的目录生成.模板套用等,极大地方便了用户完 ...

  8. 前端调用后台接口下载word文档的两种方法

    1传统的ajax虽然能提交到后台,但是返回的数据被解析成json,html,text等字符串,无法响应浏览器下载.就算使用bob模拟下载,数据量大时也不方便 废话不多说:上代码(此处是Layui监听提 ...

  9. .NET通过调用Office组件导出Word文档

    .NET通过调用Office组件导出Word文档 最近做项目需要实现一个客户端下载word表格的功能,该功能是用户点击"下载表格",服务端将该用户的数据查询出来并生成数据到Word ...

  10. 使用PHP导出Word文档的原理和实例

    PHP操作Word文档的方法有很多,这里再为大家提供一种方法. 原理   一般,有2种方法可以导出doc文档,一种是使用com,并且作为php的一个扩展库安装到服务器上,然后创建一个com,调用它的方 ...

随机推荐

  1. Must be called at the top of a `setup` function vue3使用vue-i18n时出现的报错

    在某js文件中引入 import {useI18n} from "vue-i18n"; 使用:useI18n().t('APP_LOADING') 修改后: import i18n ...

  2. Hash中的bucket什么意思?

    这个好理解.无序容器的内部是由一个个的bucket(桶)构成的,每个bucket里面由相同hash的元素构成. 因此无序容器的搜索是先根据hash值,定位到bucket,然后再在bucket里面搜索符 ...

  3. php运行找不到命令

    这个跟环境path设置有关: 1. 找php.ini位置./www/wdlinux/apache_php-5.5.38/bin 2. 写入默认path: export PATH=$PATH:/www/ ...

  4. 记一个快捷在线接口YAPI

    在线地址:http://192.168.252.152:3000 1.idea中file下setting中plugins搜索并加载插件YAPI 2.idea中的.idea中.misc.xml文件配置. ...

  5. Linux下apache日志(按日期存放)分析与状态查看方法

    转载网址: https://blog.csdn.net/weixin_42272246/article/details/125602258

  6. 利用Intent在两个页面之间进行传值操作的具体实现

    不知道为什么,我本来使用的呼声最高的Bundle发送,但是我使用它会显示不出来,由于时间问题,我今天就先不找了,先放一下,先以完成任务为己任哈! 我们都清楚,我们基本上都是用的Intent实现的页面之 ...

  7. 声网王浩宇:RTE 场景下的 Serverless 架构挑战【RTE 2022】

    前言 在「RTE2022 实时互联网大会」中,声网云原生边缘计算团队的负责人 @王浩宇 Dylan 以<RTE 场景下的 Serverless 架构挑战 -- 声网如何兼顾后端服务的可靠.高效和 ...

  8. 给宝宝的AC自动机启蒙指南(宝宝的第一本)

    AC自动机 根据已有经验,学完虚数会变虚,然后写出的代码就不是人能看的了 所以我们来学实树罢(喜) 以上为废话博客背景 有限状态自动机 首先我们来了解一下自动机是啥. 说的通俗一点,我们可以把自动机看 ...

  9. 怎么用ChatGPT写代码,ChatGPT怎么改代码修BUG

    ChatGPT 是一个自然语言处理模型,可以模拟人类语言生成文本,可以用于写代码和修复bug.在本文中,我们将介绍如何使用 ChatGPT 写代码和修bug. 怎么用ChatGPT写代码? 虽然 Ch ...

  10. $\mathcal{Crypto}$ 共模攻击原理实现以及$\mathcal{CRT}$优化

    \(\mathcal{共模攻击概述}\) 共模攻击是一种攻击 \(\mathcal{RSA}\) 加密的技术,当两个密文使用相同的 \(\mathcal{RSA}\) 公共模数时,攻击者可以使用中国剩 ...