Skip to content

Commit

Permalink
SpringBoot初始化模板v2.1.4 设计Apache POI操作Word模块及其配套工具类。
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonyCheng committed Apr 9, 2024
1 parent f94b6a6 commit 6ef573c
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 23 deletions.
19 changes: 6 additions & 13 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
<minio.version>8.5.9</minio.version>
<!-- 文件操作相关 -->
<poi.version>5.2.5</poi.version>
<poi.tl.version>1.12.2</poi.tl.version>
<easy.excel.version>3.3.4</easy.excel.version>
<itext.version>8.0.3</itext.version>
<!-- 外部平台相关 -->
Expand Down Expand Up @@ -393,6 +394,11 @@
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>${poi.tl.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
Expand Down Expand Up @@ -513,23 +519,10 @@
<resources>
<resource>
<directory>src/main/resources</directory>
<!-- 关闭过滤 -->
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/webapp/</directory>
</resource>
<resource>
<directory>src/main/resources</directory>
<!-- 引入所有 匹配文件进行过滤 -->
<includes>
<include>application*</include>
<include>bootstrap*</include>
<include>logback*</include>
</includes>
<!-- 启用过滤 即该资源中的变量将会被过滤器中的值替换 -->
<filtering>true</filtering>
</resource>
</resources>
</build>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package top.sharehome.springbootinittemplate.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaIgnore;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
Expand All @@ -13,9 +14,11 @@
import top.sharehome.springbootinittemplate.model.dto.auth.AuthRegisterDto;
import top.sharehome.springbootinittemplate.model.vo.auth.AuthLoginVo;
import top.sharehome.springbootinittemplate.service.AuthService;
import top.sharehome.springbootinittemplate.utils.document.excel.ExcelUtils;
import top.sharehome.springbootinittemplate.utils.satoken.LoginUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
Expand All @@ -31,6 +34,13 @@ public class AuthController {
@Resource
private AuthService authService;

@GetMapping("/test")
@SaIgnore
public R<Void> test(HttpServletResponse response) {
ExcelUtils.exportTemplateHttpServletResponse("test", response);
return R.empty();
}

/**
* 注册
* todo 模板默认不使用该接口,但保留该接口,因为该模板中真实增加用户的接口应该是管理员增加用户
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;
import top.sharehome.springbootinittemplate.common.base.ReturnCode;
import top.sharehome.springbootinittemplate.config.easyexcel.convert.date.ExcelDateConverter;
Expand Down Expand Up @@ -712,29 +715,27 @@ public static <T> void exportTemplateHttpServletResponse(String templateName, Cl
}

/**
* 导出Excel模板目录下的模板文件,同时关闭请求响应流并提交响应,模板目录一定是resources文件夹下templates/excel目录
* 导出Excel.xlsx模板目录下的模板文件,同时关闭请求响应流并提交响应,模板目录一定是resources文件夹下templates/excel目录
* 在Controller中建议直接返回void,如果想要统一返回响应类型R<T>,可以使用R.empty()方法。
*
* @param templateName resource模板名称(不带后缀)
* @param response 请求响应流
* @param <T> 泛型T
*/
public static <T> void exportTemplateHttpServletResponse(String templateName, HttpServletResponse response) {
public static void exportTemplateHttpServletResponse(String templateName, HttpServletResponse response) {
try {
File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "templates/excel/" + templateName + ExcelTypeEnum.XLSX.getValue());
if (!file.isFile()) {
throw new FileNotFoundException();
ClassPathResource classPathResource = new ClassPathResource("templates/excel/" + templateName + ExcelTypeEnum.XLSX.getValue());
if (!classPathResource.exists()) {
throw new CustomizeExcelException(ReturnCode.EXCEL_FILE_ERROR, "模板文件[" + templateName + ".xlsx]未找到");
}
InputStream inputStream = classPathResource.getInputStream();
handleResponse(templateName, response);
FileInputStream fileInputStream = new FileInputStream(file);
int len = 0;
byte[] buffer = new byte[1024];
ServletOutputStream outputStream = response.getOutputStream();
while ((len = fileInputStream.read(buffer)) > 0) {
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len);
}
fileInputStream.close();
outputStream.flush();
inputStream.close();
outputStream.close();
} catch (FileNotFoundException e) {
throw new CustomizeExcelException(ReturnCode.EXCEL_FILE_ERROR, "模板文件[" + templateName + ".xlsx]未找到");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.deepoove.poi.XWPFTemplate;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Builder;
Expand All @@ -16,7 +17,9 @@
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.core.io.ClassPathResource;
import top.sharehome.springbootinittemplate.common.base.ReturnCode;
import top.sharehome.springbootinittemplate.exception.customize.CustomizeExcelException;
import top.sharehome.springbootinittemplate.exception.customize.CustomizeReturnException;

import javax.imageio.ImageIO;
Expand All @@ -38,6 +41,77 @@
@Slf4j
public class WordUtils {

/**
* 输出Word模板内部类
* 该导出模板是基于POI-TL框架的封装,该框架主要以"{{XXX}}"型标签为内容插入点,具体用法查看https://deepoove.com/poi-tl
*/
public static class Template {

/**
* 导出Word.docx模板目录下的模板文件到响应流,模板目录一定是resources文件夹下templates/word目录
*
* @param templateName 模板名称
* @param tagMap 标签Map
* @param filename 导出文件名称
* @param response 响应流
*/
public static void export(String templateName, Map<String, Object> tagMap, String filename, HttpServletResponse response) {
try {
handleWordResponse(filename, response);
ServletOutputStream outputStream = response.getOutputStream();
export(templateName, tagMap, outputStream);
} catch (IOException e) {
throw new CustomizeReturnException(ReturnCode.WORD_FILE_ERROR);
}
}

/**
* 导出Word.docx模板目录下的模板文件到输出流,模板目录一定是resources文件夹下templates/word目录
*
* @param templateName 模板名称
* @param tagMap 标签Map
* @param outputStream 输出流
*/
public static void export(String templateName, Map<String, Object> tagMap, OutputStream outputStream) {
try {
ClassPathResource classPathResource = new ClassPathResource("templates/word/" + templateName + ".docx");
if (!classPathResource.exists()) {
throw new CustomizeExcelException(ReturnCode.EXCEL_FILE_ERROR, "模板文件[" + templateName + ".docx]未找到");
}
InputStream inputStream = classPathResource.getInputStream();
XWPFTemplate template = XWPFTemplate.compile(inputStream).render(tagMap);
template.writeAndClose(outputStream);
inputStream.close();
} catch (IOException e) {
throw new CustomizeReturnException(ReturnCode.WORD_FILE_ERROR);
}
}

/**
* 处理ContentType是Word格式的响应
*
* @param fileName 文件名
* @param response 响应
*/
private static void handleWordResponse(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
String realName = null;
if (StringUtils.isBlank(fileName)) {
realName = UUID.randomUUID().toString().replace("-", "") + ".docx";
} else {
realName = UUID.randomUUID().toString().replace("-", "") + "_" + fileName + ".docx";
}
String encodeName = URLEncoder
.encode(realName, StandardCharsets.UTF_8.toString())
.replaceAll("\\+", "%20");
String contentDispositionValue = "attachment; filename=" + encodeName + ";filename*=utf-8''" + encodeName;
response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
response.setHeader("Content-disposition", contentDispositionValue);
response.setHeader("download-filename", encodeName);
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=UTF-8");
}

}

/**
* 写入Word数据内部类
*/
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/templates/word/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
### 存放Word模板的目录

0 comments on commit 6ef573c

Please sign in to comment.