之前使用freemarker导出word,可以在PC上打开,其实也是个xml类型的,转PDF都会成为xml。但是它不能在手机上打开,因为它是xml格式的。所以后来又修改了导出方式,导出标准格式的word.
1、新建Word文件,建议直接把需要替换的值就直接写上,作为需要生成文件的模板。
2、然后把后缀名.docx改为.zip,直接就变成了个压缩包,具体的目录如下:
?
?3、因为在改为压缩包前就已经把需要替换的值给写好了,在压缩包的word文件夹里有个document.xml,该文件就是模板文件。
4、把document.xml 复制出来,跟zip文件放到同一目录下。
5、document.xml和zip都要放到生成的文件的目录下,即将要生成的文件的存放目录和zip和document.xml的目录保持一致。
6、贴上生成的工具类:其中,download方法是生成完直接下载的。makeword方法是只是生成不下载。
package com.ruoyi.project.zfwttb.controller;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.config.ServerConfig;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class WordAndPdfUtil {
private static Logger logger = LoggerFactory.getLogger(WordAndPdfUtil.class);
public static void main(String[] args) throws Exception {
String basePath = "F:/";
Map<String,Object> map = new HashMap<>();
map.put("dw","zxg");
// map.put("djq","rjk");
makeWord(basePath, "wordToPdf.zip", "wordToPdf.docx", map);
}
/**
* 生成word
* @param basePath word所在的文件夹
* @param wordInZipName word改为zip后word的名字
* @param wordOutName word输出的名称
* @param dataMap word里面需要替换的参数
*/
public static String makeWord(String basePath, String wordInZipName, String wordOutName, Map<String,Object> dataMap) {
logger.info("开始创建word");
/** 指定输出word文件的路径 **/
String outFilePath = basePath + "data.xml";
File docXmlFile = new File(outFilePath);
try {
/** 初始化配置文件 **/
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
/** 加载文件 **/
configuration.setDirectoryForTemplateLoading(new File(basePath));
configuration.setClassicCompatible(true);
/** 加载模板 **/
Template template = configuration.getTemplate("document.xml");
template.setEncoding("utf-8");
logger.info("初始化配置文件,成功, 开始渲染数据");
/**数据渲染到word**/
FileOutputStream fos = new FileOutputStream(docXmlFile);
OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
Writer out = new BufferedWriter(oWriter, 10240);
logger.info("数据写入xml中");
template.process(dataMap, out);
out.close();
fos.close();
logger.info("数据写入xml完毕, 开始读取zip文件");
/**读取压缩文件**/
ZipInputStream zipInputStream = wrapZipInputStream(new FileInputStream(new File(basePath + wordInZipName)));
/**压缩文件写入到目标路径**/
File wordOutFile = new File(basePath + wordOutName);
logger.info("创建新的目录:{}", basePath + wordOutName);
wordOutFile.createNewFile();
ZipOutputStream zipOutputStream = wrapZipOutputStream(new FileOutputStream(wordOutFile));
String itemName = "word/document.xml";
/**替换参数**/
logger.info("替换相关参数");
replaceItem(zipInputStream, zipOutputStream, itemName, new FileInputStream(docXmlFile));
logger.info("word生成成功");
} catch (IOException e) {
logger.error("IO异常:{}", e.getMessage());
e.printStackTrace();
} catch (TemplateException e) {
logger.error("模板异常:{}", e.getMessage());
e.printStackTrace();
} finally {
docXmlFile.delete();
}
ServerConfig serverConfig = new ServerConfig();
String url = serverConfig.getUrl()+"/profile/agzzc/"+wordOutName;
return url;
}
/**
* word转pdf
* @param wordPath word的路径
* @param pdfPath pdf的路径
*/
// public static boolean wordToPdf(String wordPath, String pdfPath){
// logger.info("wordPath:{}, pdfPath:{}", wordPath, pdfPath);
// boolean result = false;
// try {
// logger.info("开始word转pdf");
// XWPFDocument document=new XWPFDocument(new FileInputStream(new File(wordPath)));
// File outFile=new File(pdfPath);
// outFile.getParentFile().mkdirs();
// OutputStream out=new FileOutputStream(outFile);
// PdfOptions options= PdfOptions.create();
// PdfConverter.getInstance().convert(document,out,options);
// logger.info("word转pdf成功");
// result = true;
// }
// catch ( Exception e) {
// e.printStackTrace();
// logger.error("word转pdf失败");
// }
// return result;
// }
public static void download( HttpServletResponse response,String basePath, String wordInZipName, String wordOutName, Map<String,Object> dataMap) {
logger.info("开始创建word");
/** 指定输出word文件的路径 **/
String outFilePath = basePath + "data.xml";
File docXmlFile = new File(outFilePath);
try {
/** 初始化配置文件 **/
Configuration configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
/** 加载文件 **/
configuration.setDirectoryForTemplateLoading(new File(basePath));
configuration.setClassicCompatible(true);
/** 加载模板 **/
Template template = configuration.getTemplate("document.xml");
template.setEncoding("utf-8");
logger.info("初始化配置文件,成功, 开始渲染数据");
/**数据渲染到word**/
FileOutputStream fos = new FileOutputStream(docXmlFile);
OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
Writer out = new BufferedWriter(oWriter, 10240);
logger.info("数据写入xml中");
template.process(dataMap, out);
out.close();
fos.close();
logger.info("数据写入xml完毕, 开始读取zip文件");
/**读取压缩文件**/
ZipInputStream zipInputStream = wrapZipInputStream(new FileInputStream(new File(basePath + wordInZipName)));
/**压缩文件写入到目标路径**/
File wordOutFile = new File(basePath + wordOutName);
logger.info("创建新的目录:{}", basePath + wordOutName);
wordOutFile.createNewFile();
ZipOutputStream zipOutputStream = wrapZipOutputStream(new FileOutputStream(wordOutFile));
String itemName = "word/document.xml";
/**替换参数**/
logger.info("替换相关参数");
replaceItem(zipInputStream, zipOutputStream, itemName, new FileInputStream(docXmlFile));
logger.info("word生成成功");
} catch (IOException e) {
logger.error("IO异常:{}", e.getMessage());
e.printStackTrace();
} catch (TemplateException e) {
logger.error("模板异常:{}", e.getMessage());
e.printStackTrace();
} finally {
docXmlFile.delete();
}
try {
// path是指想要下载的文件的路径
File file = new File( basePath + wordOutName);
// 获取文件名
String filename = file.getName();
// 获取文件后缀名
String ext = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();
// 将文件写入输入流
FileInputStream fileInputStream = new FileInputStream(file);
InputStream fis = new BufferedInputStream(fileInputStream);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header
response.setCharacterEncoding("UTF-8");
//Content-Disposition的作用:告知浏览器以何种方式显示响应返回的文件,用浏览器打开还是以附件的形式下载到本地保存
//attachment表示以附件方式下载 inline表示在线打开 "Content-Disposition: inline; filename=文件名.mp3"
// filename表示文件的默认名称,因为网络传输只支持URL编码的相关支付,因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
// 告知浏览器文件的大小
response.addHeader("Content-Length", "" + file.length());
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
outputStream.write(buffer);
outputStream.flush();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 替换某个 item,
* @param zipInputStream zip文件的zip输入流
* @param zipOutputStream 输出的zip输出流
* @param itemName 要替换的 item 名称
* @param itemInputStream 要替换的 item 的内容输入流
*/
public static void replaceItem(
ZipInputStream zipInputStream,
ZipOutputStream zipOutputStream,
String itemName,
InputStream itemInputStream){
if(null == zipInputStream){return;}
if(null == zipOutputStream){return;}
if(null == itemName){return;}
if(null == itemInputStream){return;}
ZipEntry entryIn;
try {
while((entryIn = zipInputStream.getNextEntry())!=null)
{
String entryName = entryIn.getName();
ZipEntry entryOut = new ZipEntry(entryName);
// 只使用 name
zipOutputStream.putNextEntry(entryOut);
// 缓冲区
byte [] buf = new byte[8*1024];
int len;
if(entryName.equals(itemName)){
// 使用替换流
while((len = (itemInputStream.read(buf))) > 0) {
zipOutputStream.write(buf, 0, len);
}
} else {
// 输出普通Zip流
while((len = (zipInputStream.read(buf))) > 0) {
zipOutputStream.write(buf, 0, len);
}
}
// 关闭此 entry
zipOutputStream.closeEntry();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//e.printStackTrace();
close(itemInputStream);
close(zipInputStream);
close(zipOutputStream);
}
}
/**
* 包装输入流
*/
public static ZipInputStream wrapZipInputStream(InputStream inputStream){
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
return zipInputStream;
}
/**
* 包装输出流
*/
public static ZipOutputStream wrapZipOutputStream(OutputStream outputStream){
ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
return zipOutputStream;
}
private static void close(InputStream inputStream){
if (null != inputStream){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static void close(OutputStream outputStream){
if (null != outputStream){
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
|