*** 所有目录参数皆为项目相对路径
org.projectlombok
lombok
true
org.apache.commons
commons-lang3
3.7
org.apache.commons
commons-io
LATEST
fr.opensagres.xdocreport
fr.opensagres.xdocreport.document
1.0.5
fr.opensagres.xdocreport
org.apache.poi.xwpf.converter.xhtml
1.0.5
org.apache.poi
poi-scratchpad
3.12
public static String getRealPath(String dirPath) {
//利用资源加载器获取资源URL
String path = Class.class.getResource("/").getPath();
return path + dirPath;
}
/**
* 获取目录下所有文件(默认不存在目录下同时存在文件和文件夹)
*
* @param targetPath
* @return
*/
public static List getFiles(String targetPath) {
String realPath = getRealPath(targetPath);
List list = new ArrayList<>();
if (StringUtils.isBlank(realPath)) {
return null;
}
File file = new File(realPath);
if (file.isFile()) {
list.add(file);
return list;
} else {
File[] files = file.listFiles();
return files == null ? null : Arrays.asList(files);
}
}
/**
* 注意dataMap里存放的数据Key值要与模板中的参数相对应
*
* @param target
*/
private static Map getData(Object target) {
Map map = new HashMap<>();
Class> beanClass = target.getClass();
Field[] declaredFields = beanClass.getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
String key = field.getName();
Object value = null;
try {
value = field.get(target);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if(value == null) {
value = "";
}
map.put(key, value);
}
return map;
}
private static void writeFile(String content, String path) {
FileOutputStream fos = null;
BufferedWriter bw = null;
try {
File file = new File(path);
if (!file.exists()) {
boolean newFile = file.createNewFile();
}
fos = new FileOutputStream(file);
bw = new BufferedWriter(new OutputStreamWriter(fos));
bw.write(content);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bw != null) {
bw.close();
}
if (fos != null) {
fos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 生成word文件
*
* @param templatePath
* @param fileName
* @param targetFilePath
* @param target
*/
public static void createDoc(String templatePath, String fileName, String targetFilePath,Object target) {
//要填入模本的数据文件
Map data = getData(target);
//设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载,
//这里我们的模板是放在com.phq.document.template包下面
configuration.setClassForTemplateLoading(FileUtils.class, templatePath);
Template t = null;
try {
//test.ftl为要装载的模板
t = configuration.getTemplate(fileName);
} catch (IOException e) {
e.printStackTrace();
}
if(t == null) {
return;
}
//输出文档路径及名称
File outFile = new File(getRealPath(targetFilePath));
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
t.process(data, out);
} catch (TemplateException | IOException e) {
e.printStackTrace();
}
}
/**
* 将word转换成html
* 支持 .doc and .docx
*
* @param filePath word路径
* @param outPutFilePath html存储路径 形式如"/file/"
* @param newFileName html名
* @throws TransformerException
* @throws IOException
* @throws ParserConfigurationException
*/
public static void wordToHtml(String filePath, String outPutFilePath, String newFileName)
throws TransformerException, IOException, ParserConfigurationException {
String substring = filePath.substring(filePath.lastIndexOf(".") + 1);
ByteArrayOutputStream out = new ByteArrayOutputStream();
outPutFilePath = getRealPath(outPutFilePath);
filePath = getRealPath(filePath);
//防止错误输入
if(!outPutFilePath.endsWith("/") && !outPutFilePath.endsWith("\\")) {
outPutFilePath = outPutFilePath + "/";
}
/*
* word2007和word2003的构建方式不同,
* 前者的构建方式是xml,后者的构建方式是dom树。
* 文件的后缀也不同,前者后缀为.docx,后者后缀为.doc
* 相应的,apache.poi提供了不同的实现类。
*/
if ("docx".equals(substring)) {
InputStream inputStream = new FileInputStream(new File(filePath));
XWPFDocument document = new XWPFDocument(inputStream);
//step 2 : prepare XHTML options
final String imageUrl = "";
XHTMLOptions options = XHTMLOptions.create();
options.setExtractor(new FileImageExtractor(new File(outPutFilePath + imageUrl)));
options.setIgnoreStylesIfUnused(false);
options.setFragment(true);
// @Override 重写的方法,加上这个报错,你看看是啥问题
options.URIResolver(uri -> imageUrl + uri);
//step 3 : convert XWPFDocument to XHTML
XHTMLConverter.getInstance().convert(document, out, options);
} else {
HWPFDocument wordDocument = new HWPFDocument(new FileInputStream(filePath));
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.newDocument());
wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> suggestedName);
wordToHtmlConverter.processDocument(wordDocument);
//save pictures
List pics = wordDocument.getPicturesTable().getAllPictures();
if (pics != null) {
for (int i = 0; i < pics.size(); i++) {
Picture pic = (Picture) pics.get(i);
System.out.println();
try {
pic.writeImageContent(new FileOutputStream(outPutFilePath
+ pic.suggestFullFileName()));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Document htmlDocument = wordToHtmlConverter.getDocument();
DOMSource domSource = new DOMSource(htmlDocument);
StreamResult streamResult = new StreamResult(out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer serializer = tf.newTransformer();
serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty(OutputKeys.METHOD, "html");
serializer.transform(domSource, streamResult);
}
out.close();
writeFile(new String(out.toByteArray()), outPutFilePath + newFileName);
}
基于ftl模版生成的doc文档,其实际类型还是xml格式,在转化成HTML格式时失败,于是整合网上各类资料,以及自己的努力探索,得出以下方法来实现基于docx模板生成docx文档。
/**
* 实现word文档填充
*
* @param inFile
* word模板路径和名称
* @param bean
* 待填充的数据,从数据库读取
* @throws IOException
*/
public static void fillDocx(String inFile,String outFile, Object bean) throws IOException {
Map data = getData(bean);
InputStream is = new FileInputStream(FileUtils.getPath(inFile));
XWPFDocument document;
try {
document = new XWPFDocument(OPCPackage.open(is));
// 替换段落里面的变量
replaceInPara(document, data);
OutputStream os = new FileOutputStream(FileUtils.getPath(outFile));
document.write(os);
os.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 替换段落里面的变量
*
* @param doc
* 要替换的文档
* @param params
* 参数
*/
private static void replaceInPara(XWPFDocument doc, Map params) {
Iterator iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
replaceInPara(para, params);
}
}
/**
* 替换段落里面的变量
*
* @param para
* 要替换的段落
* @param params
* 参数
*/
private static void replaceInPara(XWPFParagraph para, Map params) {
List runs;
Matcher matcher;
String runText = "";
if (pattern.matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
if (runs.size() > 0) {
int j = runs.size();
for (int i = 0; i < j; i++) {
XWPFRun run = runs.get(0);
String i1 = run.toString();
runText += i1;
para.removeRun(0);
}
}
matcher = pattern.matcher(runText);
if (matcher.find()) {
while ((matcher = pattern.matcher(runText)).find()) {
String value = String.valueOf(params.get(matcher.group(1)));
if (value.equals("null")) {
value = "";
}
runText = matcher.replaceFirst(value);
}
// 直接调用XWPFRun的setText()方法设置文本时,在底层会重新创建一个XWPFRun,把文本附加在当前文本后面,
// 所以我们不能直接设值,需要先删除当前run,然后再自己手动插入一个新的run。
para.insertNewRun(0).setText(runText);
}
}
}
/**
* 将word转换成html
* 支持 .doc and .docx
*
* @param filePath word路径
* @param outPutFilePath html存储路径 形式如"/file/"
* @param newFileName html名
* @throws TransformerException
* @throws IOException
* @throws ParserConfigurationException
*/
public static void wordToHtml(String filePath, String outPutFilePath, String newFileName)
throws TransformerException, IOException, ParserConfigurationException {
String substring = filePath.substring(filePath.lastIndexOf(".") + 1);
ByteArrayOutputStream out = new ByteArrayOutputStream();
outPutFilePath = FileUtils.getPath(outPutFilePath);
filePath = FileUtils.getPath(filePath);
//防止错误输入
if (!outPutFilePath.endsWith("/") && !outPutFilePath.endsWith("\\")) {
outPutFilePath = outPutFilePath + "/";
}
/*
* word2007和word2003的构建方式不同,
* 前者的构建方式是xml,后者的构建方式是dom树。
* 文件的后缀也不同,前者后缀为.docx,后者后缀为.doc
* 相应的,apache.poi提供了不同的实现类。
*/
if ("docx".equals(substring)) {
InputStream inputStream = new FileInputStream(new File(filePath));
XWPFDocument document = new XWPFDocument(inputStream);
//step 2 : prepare XHTML options
final String imageUrl = "";
XHTMLOptions options = XHTMLOptions.create();
options.setExtractor(new FileImageExtractor(new File(outPutFilePath + imageUrl)));
options.setIgnoreStylesIfUnused(false);
options.setFragment(true);
// @Override 重写的方法,加上这个报错,你看看是啥问题
options.URIResolver(uri -> imageUrl + uri);
//step 3 : convert XWPFDocument to XHTML
XHTMLConverter.getInstance().convert(document, out, options);
} else {
HWPFDocument wordDocument = new HWPFDocument(new FileInputStream(filePath));
WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
DocumentBuilderFactory.newInstance().newDocumentBuilder()
.newDocument());
wordToHtmlConverter.setPicturesManager((content, pictureType, suggestedName, widthInches, heightInches) -> suggestedName);
wordToHtmlConverter.processDocument(wordDocument);
//save pictures
List