docx
docx是Microsoft Office2007之后版本使用的,用新的基于XML的压缩文件格式取代了其目前专有的默认文件格式,在传统的文件名扩展名后面添加了字母“x”(即“.docx”取代“.doc”、“.xlsx”取代“.xls”、“.pptx”取代“.ppt”)。
如何做导出
docx是一个压缩文件,所以要导出docx就必须要先进行解压,然后进行模板替换。再压缩为docx。
目录结构如下:
踩坑记录:
导入的图片后缀必须为jpeg
。
代码实现
压缩解压代码
package com.hengyi.docxdemo;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
/**
*
* @author dongzp
* @date 2019-03-20
* @version 1.0
*/
public class ZipUtils {
/**
* 使用GBK编码可以避免压缩中文文件名乱码
*/
private static final String CHINESE_CHARSET = "GBK";
/**
* 文件读取缓冲区大小
*/
private static final int CACHE_SIZE = 1024;
/**
*
* 压缩文件
*
*
* @param sourceFolder 压缩文件夹
* @param zipFilePath 压缩文件输出路径
* @throws Exception
*/
public static void zip(String sourceFolder, String zipFilePath) throws Exception {
OutputStream out = new FileOutputStream(zipFilePath);
BufferedOutputStream bos = new BufferedOutputStream(out);
ZipOutputStream zos = new ZipOutputStream(bos);
// 解决中文文件名乱码
// zos.setEncoding(CHINESE_CHARSET);
File file = new File(sourceFolder);
String basePath = null;
if (file.isDirectory()) {
basePath = file.getPath();
} else {
basePath = file.getParent();
}
zipFile(file, basePath, zos);
zos.closeEntry();
zos.close();
bos.close();
out.close();
}
/**
*
* 递归压缩文件
*
*
* @param parentFile
* @param basePath
* @param zos
* @throws Exception
*/
private static void zipFile(File parentFile, String basePath, ZipOutputStream zos) throws Exception {
File[] files;
if (parentFile.isDirectory()) {
files = parentFile.listFiles();
} else {
files = new File[1];
files[0] = parentFile;
}
String pathName;
InputStream is;
BufferedInputStream bis;
byte[] cache = new byte[CACHE_SIZE];
for (File file : files) {
if (file.isDirectory()) {
zipFile(file, basePath, zos);
} else {
pathName = file.getPath().substring(basePath.length() + 1);
is = new FileInputStream(file);
bis = new BufferedInputStream(is);
zos.putNextEntry(new ZipEntry(pathName));
int nRead = 0;
while ((nRead = bis.read(cache, 0, CACHE_SIZE)) != -1) {
zos.write(cache, 0, nRead);
}
bis.close();
is.close();
}
}
}
/**
*
* 解压压缩包
*
*
* @param zipFilePath 压缩文件路径
* @param destDir 压缩包释放目录
* @throws Exception
*/
/**
* 解压文件
* @param zipPath 要解压的目标文件
* @param descDir 指定解压目录
* @return 解压结果:成功,失败
*/
public static boolean unZip(String zipPath, String descDir) {
File zipFile = new File(zipPath);
boolean flag = false;
File pathFile = new File(descDir);
if(!pathFile.exists()){
pathFile.mkdirs();
}
ZipFile zip = null;
try {
zip = new ZipFile(zipFile, Charset.forName("gbk"));//防止中文目录,乱码
for(Enumeration entries = zip.entries(); entries.hasMoreElements();){
ZipEntry entry = (ZipEntry)entries.nextElement();
String zipEntryName = entry.getName();
InputStream in = zip.getInputStream(entry);
//指定解压后的文件夹+当前zip文件的名称
String outPath = (descDir+zipEntryName).replace("/", File.separator);
//判断路径是否存在,不存在则创建文件路径
File file = new File(outPath.substring(0, outPath.lastIndexOf(File.separator)));
if(!file.exists()){
file.mkdirs();
}
//判断文件全路径是否为文件夹,如果是上面已经上传,不需要解压
if(new File(outPath).isDirectory()){
continue;
}
//保存文件路径信息(可利用md5.zip名称的唯一性,来判断是否已经解压)
System.err.println("当前zip解压之后的路径为:" + outPath);
OutputStream out = new FileOutputStream(outPath);
byte[] buf1 = new byte[2048];
int len;
while((len=in.read(buf1))>0){
out.write(buf1,0,len);
}
in.close();
out.close();
}
flag = true;
zip.close();
} catch (IOException e) {
e.printStackTrace();
}
return flag;
}
public static void main(String[] args){
//1.压缩一个文件
try {
unZip("E:\\zzzz.zip","E:\\zzzz\\");
System.out.println("压缩完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
最终实现
/**
* Created:2019/3/20
* Time:9:32
* Author:dongzp
* Email:[email protected]
* Project:docx-demo
* Use:
*/
public class WordDocxExportUtil {
/*
* 实现文件的拷贝
* @param srcPathStr
* 源文件的地址信息
* @param desPathStr
* 目标文件的地址信息
*/
private static String copyFile(String srcPathStr, String desPath,String newFileName) {
newFileName = "image" + newFileName + ".jpeg";
desPath = desPath + File.separator + newFileName;
try{
//2.创建输入输出流对象
FileInputStream fis = new FileInputStream(srcPathStr);
FileOutputStream fos = new FileOutputStream(desPath);
//创建搬运工具
byte datas[] = new byte[1024*8];
//创建长度
int len = 0;
//循环读取数据
while((len = fis.read(datas))!=-1){
fos.write(datas,0,len);
}
//3.释放资源
fis.close();
fos.close();
return newFileName;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 清空媒体文件
* @param media
*/
private static void clearMediaFile(File media){
System.out.println("meida:" + media.isDirectory());
if(media.isDirectory()){
File[] fileList = media.listFiles();
if(fileList != null){
for(File file : fileList)
if(file.exists())
file.delete();
}
}
}
/**
* 模板替换
* @param templateFile
* @param distFile
*/
private static void templateReplace(String templateDir,String templateFile,String distFile,Map data)throws Exception{
Configuration config = new Configuration();
config.setDirectoryForTemplateLoading(new File(templateDir));
config.setObjectWrapper(new DefaultObjectWrapper());
Template template = config.getTemplate(templateFile, "UTF-8");
FileOutputStream fos = new FileOutputStream(distFile);
Writer out = new OutputStreamWriter(fos, "UTF-8");
template.process(data, out);
out.flush();
out.close();
}
/**
* 导出Docx
* @param outFile 导出的目录
* @param template 模板文件根目录
* @param documentFtl document模板文件
* @param documentRelsFtl documentRels模板文件
* @param data document数据
* @param images documentRles数据
* @return
* @throws Exception
*/
public static void exportDocx(File outFile,File template,File documentFtl,File documentRelsFtl,Map data,List