java实现word批量多模版(浏览器zip压缩导出)
·
用java实现word导出,如果不实现批量导出,可以只使用 word 替换工具,如果要实现批量导出,这里的解决办法是将所有的导出文件放入服务器临时文件,压缩后导出
1.依赖包
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>3.0.3</version>
</dependency>
2. word模板替换工具
package com.**.**.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.util.Assert;
// 这是俩个常量包 BIAS = "/" , MSIE = "MSIE",TRIDENT = "Trident",MOZILLA = "Mozilla"
import com.***.***.core.constants.CoreConstant;
import com.***.***.web.constants.EquipmentComputeConstants;
import cn.afterturn.easypoi.word.WordExportUtil;
public class ExportUtil {
/**
* 导出word
* <p>
* 第一步生成替换后的word文件,只支持docx
* </p>
* <p>
* 第二步下载生成的文件
* </p>
* <p>
* 第三步删除生成的临时文件
* </p>
* 模版变量中变量格式:{{foo}}
*
* @param templatePath
* word模板地址
* @param temDir
* 生成临时文件存放地址
* @param fileName
* 文件名
* @param params
* 替换的参数
* @param request
* HttpServletRequest
* @param response
* HttpServletResponse
* @throws IOException
*/
public static void exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params,
HttpServletRequest request, HttpServletResponse response) throws IOException {
Assert.notNull(templatePath, "模板路径不能为空");
Assert.notNull(temDir, "临时文件路径不能为空");
Assert.notNull(fileName, "导出文件名不能为空");
Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式");
if (!temDir.endsWith(CoreConstant.BIAS)) {
temDir = temDir + File.separator;
}
File dir = new File(temDir);
if (!dir.exists()) {
dir.mkdirs();
}
FileInputStream in = null;
// OutputStream out2 = null;
try {
XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
String tmpPath = temDir + fileName;
// 写在本地
FileOutputStream fos = new FileOutputStream(tmpPath);
doc.write(fos);
/*
* ------------下载到本地------------ // 设置强制下载不打开
* response.setContentType("application/force-download"); // 设置文件名
* response.addHeader("Content-Disposition", "attachment;fileName="
* + fileName); OutputStream out = response.getOutputStream();
* doc.write(out); out.close();
*/
// -------浏览器下载--------------
// 读取要下载的文件,保存到文件输入流
in = new FileInputStream(tmpPath);
// 获得浏览器代理信息
final String userAgent = request.getHeader("USER-AGENT");
// 判断浏览器代理并分别设置响应给浏览器的编码格式
String finalFileName = null;
if (StringUtils.contains(userAgent, EquipmentComputeConstants.MSIE) || StringUtils.contains(userAgent, EquipmentComputeConstants.TRIDENT)) {// IE浏览器
finalFileName = URLEncoder.encode(fileName, "UTF8");
System.out.println("IE浏览器");
} else if (StringUtils.contains(userAgent, EquipmentComputeConstants.MOZILLA)) {// google,火狐浏览器
finalFileName = new String(fileName.getBytes(), "ISO8859-1");
} else {
finalFileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器
}
// // 缓存区
// byte buffer[] = new byte[1024];
// int len = 0;
// // 循环将输入流中的内容读取到缓冲区中
// while ((len = in.read(buffer)) > 0) {
// out2.write(buffer, 0, len);
// }
// 关闭
in.close();
// out2.close();
// 清空response
// response.reset();
} catch (Exception e) {
e.printStackTrace();
}
// 删除服务器上的临时文件
File deleteFile = new File(temDir);
deleteFile.delete();
}
}
3.zip压缩导出工具
package com.**.**.util;
import static org.springframework.util.StreamUtils.BUFFER_SIZE;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import com.**.**.exception.ResourceException;
import com.**.**.web.constants.Constants;
/**
* zip打包下载工具
* @author ****
* <p>2019年4月30日 上午9:53:21</p>
* @see
* @version 1.0
*/
public class ZipExportUtil {
/**
* 打包
* @param path 文件夹路径
*/
public static void zipExport(String path, HttpServletResponse response){
try {
response.setContentType("application/DOWLOAD");
response.setHeader("Content-Disposition", "attachment; filename="
+ DateUtils.dateToString(new Date()) + ".zip");
ServletOutputStream out = response.getOutputStream();
toZip(path, out, true);
DelAllFileUtil.delAllFile("F:\\annualAeport");
} catch (Exception e) {
throw new ResourceException(Constants.EXCEPTION_CODE_500, e.getMessage());
}
}
/**
* 打压缩包导出
*
* @param srcDir
* @param out
* @param keepDirStructure
* @throws RuntimeException
*/
public static void toZip(String srcDir, OutputStream out, boolean keepDirStructure) throws RuntimeException {
ZipOutputStream zos = null;
try {
zos = new ZipOutputStream(out);
File sourceFile = new File(srcDir);
compress(sourceFile, zos, sourceFile.getName(), keepDirStructure);
} catch (Exception e) {
throw new RuntimeException("zip error from ZipUtils", e);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
throw new ResourceException(Constants.EXCEPTION_CODE_500, e.getMessage());
}
}
}
}
/**
* 执行压缩
*
* @param sourceFile
* @param zos
* @param name
* @param keepDirStructure
* @throws Exception
*/
private static void compress(File sourceFile, ZipOutputStream zos, String name, boolean keepDirStructure)
throws Exception {
byte[] buf = new byte[BUFFER_SIZE];
if (sourceFile.isFile()) {
// 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
zos.putNextEntry(new ZipEntry(name));
// copy文件到zip输出流中
int len;
FileInputStream in = new FileInputStream(sourceFile);
while ((len = in.read(buf)) != -1) {
zos.write(buf, 0, len);
}
// Complete the entry
zos.closeEntry();
in.close();
} else {
File[] listFiles = sourceFile.listFiles();
if (listFiles == null || listFiles.length == 0) {
// 需要保留原来的文件结构时,需要对空文件夹进行处理
if (keepDirStructure) {
// 空文件夹的处理
zos.putNextEntry(new ZipEntry(name + "/"));
// 没有文件,不需要文件的copy
zos.closeEntry();
}
} else {
for (File file : listFiles) {
// 判断是否需要保留原来的文件结构
if (keepDirStructure) {
// 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
// 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
compress(file, zos, name + "/" + file.getName(), keepDirStructure);
} else {
compress(file, zos, file.getName(), keepDirStructure);
}
}
}
}
}
}
4.模板样例 文档中的替换样例用{{}}

5.模板在resources下,此处路径本地下载没问题,服务器下载要配置服务器绝对路径 (本地相对路径:/templates 服务器绝对路径:打包后web路径会加入/WEB-INF/classes 这俩层结构)

6. 控制层使用void 不return结果,否则会报错(因需求已实现,且中途改过工具,不确定,问题应该未解决)
@AspectLog(description = "批量导出word")
@ApiOperation("批量导出word")
@RequestMapping(value = "/datereporting/export", method = RequestMethod.GET)
public void export(HttpServletRequest request, HttpServletResponse response, String ids) {
try {
dateReportingService.batchExport(ids, request, response);
} catch (Exception e) {
logger.error(Constants.CONTROLLER_GET_ERROR_LOG, e.getMessage());
}
}
7. 调用替换word工具
// Map<String, Object> everyMap 为 要替换的导出数据 Map<String, Object> data 中的 键 为模板文档中的对应变量
private void exportSocialPerformanceAnalysisReport(Map<String, Object> everyMap, HttpServletRequest request,
HttpServletResponse response) throws IOException {
String year = everyMap.get("YEAR") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("YEAR").toString();
String tableName = everyMap.get("TABLE_NAME") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("TABLE_NAME").toString();
String deviceName = everyMap.get("DEVICE_NAME") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("DEVICE_NAME").toString();
String equipmentNo = everyMap.get("EQUIPMENT_NO") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("EQUIPMENT_NO").toString();
String name = everyMap.get("DEVICE_NAME") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("DEVICE_NAME").toString();
String dept = everyMap.get("APPLY_DEPARTMENT") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("APPLY_DEPARTMENT").toString();
String evaluate = everyMap.get("EVALUATE") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("EVALUATE").toString();
String presentation = everyMap.get("ANALYSIS") == null ? EquipmentComputeConstants.EXPORT_EMPTY
: everyMap.get("ANALYSIS").toString();
/* 模板文本替换 */
Map<String, Object> data = new HashMap<String, Object>(16);
data.put("year", year);
data.put("name", name);
data.put("dept", dept);
data.put("usage_situation", evaluate);
data.put("presentation", presentation);
// 拼接文件名
StringBuilder fileName = new StringBuilder();
fileName.append(year);
fileName.append(deviceName);
fileName.append(tableName);
fileName.append("(");
fileName.append(equipmentNo);
fileName.append(")");
fileName.append(".docx");
StringBuilder path = new StringBuilder();
path.append(templates);
path.append("/EquipmentPerformanceAnalysisTemplate4.docx");
ExportUtil.exportWord(path.toString(), annualAeportPath, fileName.toString(), data, request, response);
}
Map<String, Object> everyMap 为 要替换的导出数据 Map<String, Object> data 中的 键 为模板文档中的对应变量
ExportUtil.exportWord(path.toString(), annualAeportPath, fileName.toString(), data, request, response);
方法参数说明:第一个是路径,第二个是服务器或本地临时文件路径(导出文件位置),第三个是导出文件名(批量执行,文件名一致会覆盖)
8.替换后执行浏览器压缩导出
/* zip打包导出 */
ZipExportUtil.zipExport(annualAeportPath, response);
/* 删除临时文件 */
DelAllFileUtil.delAllFile(annualAeportPath);
9.测试结果




--------------------------------------------------------------------------------------------------
补充文件删除工具类:DelAllFileUtil
package com.***.util;
import java.io.File;
/**
* 删除服务器文件工具
*/
public class DelAllFileUtil {
/**
* 删除文件夹及子文件
*
* @param path 文件夹绝对路径
* @return
*/
public static boolean delAllFile(String path) {
boolean flag = false;
File file = new File(path);
if (!file.exists()) {
return flag;
}
if (!file.isDirectory()) {
return flag;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + tempList[i]);
} else {
temp = new File(path + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path + "/" + tempList[i]);// 先删除文件夹里面的文件
delFolder(path + "/" + tempList[i]);// 再删除空文件夹
flag = true;
}
}
return flag;
}
/**
* 删除文件夹
*
* @param folderPath 文件夹绝对路径
*/
public static void delFolder(String folderPath) {
try {
delAllFile(folderPath); // 删除完里面所有内容
String filePath = folderPath;
filePath = filePath.toString();
File myFilePath = new File(filePath);
myFilePath.delete(); // 删除空文件夹
} catch (Exception e) {
e.printStackTrace();
}
}
}
更多推荐


所有评论(0)