EasyPoi导出word文档,itextpdf转换pdf
文章目录
前言
一、依赖
<!--pdf-->
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j-export-fo</artifactId>
<version>6.0.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.0.6</version>
</dependency>
<!-- easypoi-->
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.1.3</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.1.3</version>
</dependency>
二、工具类
1.WordUtil
package com.luke.admin.utils;
import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.lang.Assert;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Map;
/** * @author J * @date 2020/11/19 19:14 */
public class WordUtil {
/** * 导出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 */
public static String exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
Assert.notNull(templatePath,"模板路径不能为空");
Assert.notNull(temDir,"临时文件路径不能为空");
Assert.notNull(fileName,"导出文件名不能为空");
Assert.isTrue(fileName.endsWith(".docx"),"word导出请使用docx格式");
if (!temDir.endsWith("/")){
temDir = temDir + File.separator;
}
File dir = new File(temDir);
if (!dir.exists()) {
dir.mkdirs();
}
try {
String userAgent = request.getHeader("user-agent").toLowerCase();
if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
}
XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
String tmpPath = temDir + fileName;
System.out.println(templatePath);
FileOutputStream fos = new FileOutputStream(tmpPath);
doc.write(fos);
doc.close();
fos.close();
return templatePath;
// 设置强制下载不打开
// response.setContentType("application/force-download");
// // 设置文件名
// response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
// OutputStream out = response.getOutputStream();
// doc.write(out);
// out.close();
} catch (Exception
e) {
e.printStackTrace();
} finally {
// delAllFile(temDir);//这一步看具体需求,要不要删
}
return null ;
}
}
2.PDF工具类
package com.luke.admin.utils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.springframework.core.io.ClassPathResource;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/** * @Classname PdfUtil * @Description * @Date 2020/11/20 17:01 * @Created by j */
public class PdfUtil {
private static String separator = File.separator;//文件夹路径分格符
/** * word(docx)转pdf * @param wordPath docx文件路径 * @return 生成的pdf路径 */
public static String convertDocx2Pdf(String wordPath) {
OutputStream os = null;
InputStream is = null;
try {
is = new FileInputStream(new File(wordPath));
WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
Mapper fontMapper = new IdentityPlusMapper();
fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
mlPackage.setFontMapper(fontMapper);
//输出pdf文件路径和名称
String fileName = "pdfNoMark_" + System.currentTimeMillis() + ".pdf";
// String pdfNoMarkPath = System.getProperty("java.io.tmpdir").replaceAll(separator + "$", "") + separator + fileName;
/** * windows环境 */
String pdfNoMarkPath = "D:" + separator + fileName;
/** * linux环境 */
// String pdfNoMarkPath = "/java/word/" + separator + fileName;
os = new java.io.FileOutputStream(pdfNoMarkPath);
//docx4j docx转pdf
FOSettings foSettings = Docx4J.createFOSettings();
foSettings.setWmlPackage(mlPackage);
Docx4J.toFO(foSettings, os, Docx4J.FLAG_EXPORT_PREFER_XSL);
is.close();//关闭输入流
os.close();//关闭输出流
//添加水印
return pdfNoMarkPath;
} catch (Exception e) {
e.printStackTrace();
try {
if(is != null){
is.close();
}
if(os != null){
os.close();
}
}catch (Exception ex){
ex.printStackTrace();
}
}finally {
File file = new File(wordPath);
if(file!=null&&file.isFile()&&file.exists()){
file.delete();
}
}
return "";
}
}
3.测试
@PostMapping("/export")
public EcpResult export(@RequestBody Map<String,Object> params , HttpServletRequest request, HttpServletResponse response){
String name = System.currentTimeMillis() + ".docx";
String tem = "D:/";
// String tem = "/java/word/";
WordUtil.exportWord("word/export.docx",tem,name,params,request,response);
PdfUtil.convertDocx2Pdf(tem+name);
return EcpResult.success(tem+name);
}
注意:
1、Centos和Windows环境
在Windows环境下可以正常使用,但是在Liunx环境下需要配置中文字体, 将window上的字体打包( C:\Windows\Fonts),选择中文字体就行,上传到Ubuntu系统(/usr/share/fonts/dejavu ), 刷新缓存、重启服务就好。 1、Windows: C:\Windows\Fonts
2、Liunx:/usr/share/fonts/dejavu
3、刷新字体缓存:
fc-cache -fv
4、重启服务
2、配置缓存问题
第一次进行转换的时候读取很多配置文件,导致转换时间过长,可能会导致接口超时(测试最长10s左右)后面再次调用响应时间基本上在ms级别,建议在系统启动的时候进行配置缓存,也就是把对应的方法调用一次。