需求是:从一个word文件中读取段落和图片,存放到word模板中。
代码如下:
//通过模板生成文件,保存并导出
@RequestMapping("/exportTemplate")
public ResponseEntity<byte[]> exportTemplate(@RequestParam("id") Integer id, @RequestParam("files") String files, HttpServletRequest request, HttpServletResponse response) throws Exception {
getLicense();
Templates template = templatesService.getById(id);
String templatePath = template_path;
if (template != null) {
templatePath += template.getTemplateFilePath();
} else {
return null;
}
//读取选定的模板文件的配置项
List<TemplateProperties> templatePropertiesList = templatePropertiesService.list(new QueryWrapper<TemplateProperties>()
.eq("template_id", template.getId())
);
File path = new File(ResourceUtils.getURL("classpath:").getPath());
//获取模板文件的存放路径。
String templateFilesPath = path.getAbsolutePath() + templatePath;
//加载模板文件
Document document = new Document(templateFilesPath);
Map<String, Object> datas = new HashMap<String, Object>();
//替换模板文件中的配置项内容
if (templatePropertiesList != null && templatePropertiesList.size() > 0) {
for (TemplateProperties templateProperties : templatePropertiesList) {
datas.put(templateProperties.getTemplateName(), templateProperties.getPropertiesValue());
document.getRange().replace(templateProperties.getTemplateName(), templateProperties.getPropertiesValue(), false, false);
}
}
//获取用来加载生成模板的文件
files = files.replace(",,", ",");
Section[] sections = document.getSections().toArray();
//获取目录的位置和正文的位置
Run runContent = null, runTOC = null;
for (Section section : sections) {
//获取模板文件中的段落
Paragraph[] paragraphs = section.getBody().getParagraphs().toArray();
for (Paragraph paragraph : paragraphs) {
Run[] runs = paragraph.getRuns().toArray();
for (Run run : runs) {
if (run.getText().contains("{{content}}")) {
runContent = run;
} else if (run.getText().contains("{{toc}}")) {
runTOC = run;
}
}
}
}
DocumentBuilder builder = new DocumentBuilder(document);
if (runContent != null) {
//替换正文
builder.moveTo(runContent);
for (String file : files.split(",")) {
String readFilePath = path + file;
FileInputStream fs = new FileInputStream(readFilePath);
Document doc = new Document(fs);
fs.close();
Section[] sectionFiless = doc.getSections().toArray();
int iTemp = 0;
for (Section sectionFile : sectionFiless) {
//获取模板文件中的段落
Paragraph[] paras = sectionFile.getBody().getParagraphs().toArray();
for (Paragraph para : paras) {
boolean ifTitleFlag = false;//是否是标题,即word版式中的标题一、二等,用于最后生成目录
if (para.getParagraphFormat().getStyleName() != null) {
if (para.getParagraphFormat().getStyleIdentifier() == 1) {
builder.getParagraphFormat().setFirstLineIndent(0);
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.HEADING_1);
Font font = builder.getFont();
font.setSize(18);
font.setColor(new Color(91, 155, 213));
//font.setColor(new Color(192, 0, 0));
font.setBold(true);
builder.writeln(para.getText().trim());
ifTitleFlag = true;
} else if (para.getParagraphFormat().getStyleIdentifier() == 2) {
builder.getParagraphFormat().setFirstLineIndent(0);
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.HEADING_2);
Font font = builder.getFont();
font.setSize(15);
font.setColor(new Color(0, 0, 0));
font.setBold(true);
builder.writeln(para.getText().trim());
ifTitleFlag = true;
}
}
if (!ifTitleFlag) { //如果不是标题,则按普通文字保存格式
builder.getParagraphFormat().setFirstLineIndent(20);
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.BODY_TEXT);
Font font = builder.getFont();
font.setSize(12);
font.setColor(new Color(0, 0, 0));
font.setBold(false);
builder.writeln(para.getText().trim());
}
//获取段落后的图片,保存到段落之后
Node[] children = para.getChildNodes().toArray();
for (Node child : children) {
if (child.getNodeType() == NodeType.SHAPE) {
Shape shape = (Shape) child;
Image images = shape.getImageData().toImage();
builder.getParagraphFormat().setFirstLineIndent(0);
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.BODY_TEXT);
builder.insertImage((BufferedImage) images);
}
}
}
}
}
//移除正文标志的 {{content}}标签
runContent.remove();
}
if (runTOC != null) {
//移动到目录位置生成目录
builder.moveTo(runTOC);
builder.insertTableOfContents("\\o \"1-3\" \\h \\z \\u");
runTOC.remove();
}
//更新目录的域信息
document.updateFields();
//初始化输出流
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
//将文档以docx格式保存到输出流中
document.save(byteOut, SaveFormat.DOCX);
//保存文件
String fileName = id + "_" + DateTools.getDateString(new Date()) + ".docx";
String folderDateString = DateTools.getDateDayString(new Date());
String filePath = "/statics/upload/" + folderDateString;
String saveFileNamePath = filePath + "/" + id + "/" + fileName;
document.save(saveFileNamePath, SaveFormat.DOCX);
//开启新线程,执行保存历史记录任务
Runnable task = () -> {
// 在这里执行你的任务
TemplateHistoryFiles templateHistoryFiles = new TemplateHistoryFiles();
templateHistoryFiles.setTemplateId(id);
templateHistoryFiles.setFilePath(saveFileNamePath);
templateHistoryFiles.setGenerateDate(DateTools.getDateToStr(new Date()));
templateHistoryFiles.setGenerateUser(username);
templateHistoryFiles.setPropertiesValue(JSON.toJSONString(datas));
templateHistoryFilesService.save(templateHistoryFiles);
};
Thread thread = new Thread(task);
thread.start();
//生成下载文件
HttpHeaders headers = new HttpHeaders();
//下载显示的文件名,并解决中文名称乱码问题
String downloadFileName = new String(fileName.getBytes(StandardCharsets.UTF_8.name()), StandardCharsets.ISO_8859_1.name());
//通知浏览器以attachment(下载方式)打开
headers.setContentDispositionFormData("attachment", downloadFileName);
//applicatin/octet-stream: 二进制流数据(最常见的文件下载)
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
byte[] byteArr = byteOut.toByteArray();
return new ResponseEntity<byte[]>(byteArr, headers, HttpStatus.CREATED);
}
//获取aspose.words的license文件
public boolean getLicense() {
boolean result = false;
try {
ApplicationHome home = new ApplicationHome(getClass());
File jarFile = home.getSource();
//System.out.println("=================" + jarFile.getParentFile().getParentFile().toString());
File file = new File(jarFile.getParentFile().getParentFile().toString() + "/license.xml");
if (file.exists()) {
InputStream is = new FileInputStream(file);
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
}
} catch (Exception e) { //异常处理
e.printStackTrace();
}
return result;
}