导出Word文档
framework摸版方式
导入依赖
用到一个工具包,你也可用自己的代码实现
<!--framework-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>last</version>
</dependency>
<!--hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
代码
WordUtil.java
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
@Slf4j
public class WordUtils {
/**
* 创建word
* @param path Template下的文件路径
* @param name 摸版文件名称 不要.ftl
* @param downloadFileName 下载文件名
* @param dataMap 磨板填充数据
* @param response HttpServletResponse
* @throws IOException
*/
public static void createDocx(String path, String name,String downloadFileName,Map<String, Object> dataMap, HttpServletResponse response) throws IOException {
String fileName = URLEncoder.encode(downloadFileName+"_" + DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmss") + ".docx", "UTF-8");
response.setContentType("application/vnd.ms-word;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
WordUtils.createDocx(null, path+"/"+name+".ftl", path+"/"+name+".zip", dataMap, response.getOutputStream());
}
/**
* 图片处理:
* 需要在document.xml.rels文件中设置每张图片,格式如下:
* <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.jpeg"/>
* 在document.xml中可通过Id进行引用
* r:embed=Id
* 构建数据(dataMap)传入模板前,需要设置picList,
* dataMap.put("picList",new ArrayList<Map<String,Object>>())
* Map中需要含有name:图片名称 code:图片ByteArrayInputStream
*
* @param xmlRelsTemplateName 图片资源路径
* @param documentTemplateName word摸版/.flt
* @param templateZip Word的修改后缀 docx->zip
* @param dataMap 摸版数据、变量
* @param outputStream 输出流
*/
public static void createDocx(String xmlRelsTemplateName, String documentTemplateName, String templateZip, Map<String, Object> dataMap, OutputStream outputStream) {
try (OutputStream os = outputStream; ZipOutputStream zipOut = new ZipOutputStream(os)) {
ByteArrayInputStream documentXmlRelsInput = null;
if (StrUtil.isNotBlank(xmlRelsTemplateName)) {
//图片配置文件模板
documentXmlRelsInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, xmlRelsTemplateName);
}
Assert.hasText(documentTemplateName, "内容模板不能为空");
//内容模板
ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, documentTemplateName);
Assert.hasText(templateZip, "初始模板不能为空");
File docxFile = ResourceUtils.getFile("classpath:templates" + templateZip);
ZipFile zipFile = new ZipFile(docxFile);
// 压缩包内容
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
//开始覆盖文档------------------
int len = -1;
byte[] buffer = new byte[1024];
while (zipEntrys.hasMoreElements()) {
ZipEntry next = zipEntrys.nextElement();
InputStream is = zipFile.getInputStream(next);
if (!next.toString().contains("media")) {
zipOut.putNextEntry(new ZipEntry(next.getName()));
boolean customWrite = false;
if (next.getName().indexOf("document.xml.rels") > 0) {
if (documentXmlRelsInput != null) {
customWrite = true;
while ((len = documentXmlRelsInput.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
documentXmlRelsInput.close();
}
}
if ("word/document.xml".equals(next.getName())) {
if (documentInput != null) {
customWrite = true;
while ((len = documentInput.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
documentInput.close();
}
}
if (!customWrite) {
while ((len = is.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
is.close();
}
}
}
//写入图片
List<Map<String, Object>> picList = (List<Map<String, Object>>) dataMap.get("picList");
if (picList != null && picList.size() > 0) {
for (Map<String, Object> pic : picList) {
ZipEntry next = new ZipEntry("word" + StrPool.SLASH + "media" + StrPool.SLASH + pic.get("name"));
zipOut.putNextEntry(new ZipEntry(next.toString()));
InputStream in = (ByteArrayInputStream) pic.get("code");
while ((len = in.read(buffer)) != -1) {
zipOut.write(buffer, 0, len);
}
in.close();
}
}
} catch (Exception e) {
log.error("word导出失败:" + e.getMessage());
}
}
}