一般的导出,不对图片进行处理的话,下载后图片由于访问问题不能在word(尤其是office)中正常显示.所以导出时最好将图片转成base64,将base64的图片放到word中再导出即可;此处记录下工作中的导出方式,以备后用;
为达到导出带有样式格式的文本如:
![0435d17e45bdc3703274a2cccd523e08.png](https://i-blog.csdnimg.cn/blog_migrate/82af5b64a34cd082bd42ecffd5476f00.png)
有以下三步来实现:
1.用html实现上面的样式:
![1c65599d14b6d0c145cf062657c77a2a.png](https://i-blog.csdnimg.cn/blog_migrate/a18c59f65e3e756089df5b34ad00bf52.jpeg)
其中标红的地方是需要用数据替换的内容,可以理解为占位符;
2.提前整理需要的数据结构,可以使个Map或者是个list,将上面的html作为字符串处理,通过对所需数据的遍历,将对应数据放到对应的位置;
public String createPaperHtml(Map<String, Object> dataMap,Integer type,List<String> info){
String dataHtml=null;
String from = "<!DOCTYPE html>n" +
"<html lang="en">n" +
"<head>n" +
" <meta charset="UTF-8">n" +
" <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">n" +
" <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">n" +
" <title>试卷试题</title>n" +
" <style>n" +
" html,body,p,ul,li,h1,h2,h3,h4,h5,h6{n" +
" margin: 0;n" +
" padding: 0;n" +
" }n" +
" html,body{n" +
" width: 100%;n" +
" height: 100%;n" +
" background-color: #ffffff;n" +
" font-family: '宋体';n" +
" }n" +
"n" +
" .clearfix:after{n" +
" display: block;n" +
" content: ".";n" +
" height: 0;n" +
" clear: both;n" +
" visibility: hidden;n" +
" }n" +
" .fl{n" +
" float: left;n" +
" }n" +
" .fr {n" +
" float: right;n" +
" }n" +
"n" +
"n" +
" .exam_paper_container {n" +
" padding: 0 20px;n" +
" }n" +
" .exam_paper_container .exam_paper_title {n" +
" font-size: 20px;n" +
" text-align: center;n" +
" padding-top: 30px;n" +
" padding-bottom: 20px;n" +
" }n" +
"n" +
" .exam_paper_container .questions_wrapper h3{n" +
" font-size: 16px;n" +
" padding-bottom: 16px;n" +
" }n" +
"n" +
" .exam_paper_container .questions_wrapper .sq_question_body {n" +
" padding-bottom: 10px;n" +
" }n" +
"n" +
" .exam_paper_container .questions_wrapper .sq_question_structure {n" +
" font-size: 14px;n" +
" line-height: 20px;n" +
" padding-bottom: 4px;n" +
" }n" +
"n" +
" .exam_paper_container .sq_question_structure .structure_type {n" +
" color: blue;n" +
" }n" +
"n" +
" .exam_paper_container .sq_question_structure .structure_answer {n" +
" padding: 6px 0 0 10px;n" +
" }n" +
" </style>n" +
"</head>n" +
"<body>";
String end = "</div</div></body></html>";
StringBuffer buffer = new StringBuffer();
buffer = buffer.append(from)
.append("<div class="exam_paper_container">")
.append("<h2 class="exam_paper_title">")
.append(dataMap.get("title"))//试卷标题
.append("</h2>")
.append("<div class="questions_wrapper">");
//获取试卷题目信息;
List<QuestionGroupPvo> quesGroup = CastUtils.cast(dataMap.get("quesGroups"));
if(!CollectionUtils.isNullOrEmpty(quesGroup)){
Integer qnum = 1;
for(QuestionGroupPvo gq:quesGroup){
//大题
String qnumCh = ChineseCharacterUtils.toChinese(qnum.toString())+"、"+gq.getGroupTitle();
buffer.append(" <div class="questions_wrapper_item">")
.append("<h3>")
.append(qnumCh)
.append("(共 ")
.append(gq.getQuestLen())
.append("题;共")
.append(gq.getGroupScore())
.append("分)")
.append("</h3>");
if(!CollectionUtils.isNullOrEmpty(gq.getQuestions())){
//小题
int i=0;
for (QuestionPvo que:gq.getQuestions()){
buffer.append("<div class="questions_wrapper_item_sq">")
.append("<div class="sq_question_body">")//题干
.append(i+1).append(".");
if(info.contains("score")&&que.getScore()!=null) {
buffer.append("(").append(que.getScore()).append("分) ");
}
buffer.append(que.getBody())
.append("</div>");
if(type.equals(2)) {//教师用卷
//答案
if (info.contains("answer")&&!StringUtils.isNullOrBlank(que.getResult())) {
buffer.append("<div class="sq_question_structure">n" +
" <span class="structure_type">【答案】</span><span>")
.append(que.getResult())
.append("</span>n" +
" </div>");
}
//考点
if (info.contains("knowledge")&&!StringUtils.isNullOrBlank(que.getKnowledge())) {
buffer.append("<div class="sq_question_structure">n" +
" <span class="structure_type">【考点】</span><span>");
String knowPointStr = this.getKnowPointStr(que.getKnowledge());
buffer.append(knowPointStr)
.append("</span>n" +
" </div>");
}
//解析
if (info.contains("analysis")&&!StringUtils.isNullOrBlank(que.getAnalysis())) {
buffer.append("<div class="sq_question_structure">n" +
" <span class="structure_type">【解析】</span><span>")
.append(que.getAnalysis())
.append("</span>n" +
" </div>");
}
}
buffer.append("</div>");
i++;
}
}
buffer.append("</div>");
qnum++;
}
if(type.equals(1)){//学生用卷答案解析部分
buffer.append("<div class="exam_paper_container">n" +
" <h2 class="exam_paper_title">答案解析部分</h2> n" +
" <div class="questions_wrapper">");
Integer qq=1;
for(QuestionGroupPvo gqInfo:quesGroup){
String qnumCh1 = ChineseCharacterUtils.toChinese(qq.toString())+"、"+gqInfo.getGroupTitle();
buffer.append("<p class="question_item_title">")
.append(qnumCh1)
.append("</p>");
if(!CollectionUtils.isNullOrEmpty(gqInfo.getQuestions())){
int j=0;
for(QuestionPvo queInfo:gqInfo.getQuestions()){
//答案:
if(info.contains("answer")) {
String answerStr = !StringUtils.isNullOrBlank(queInfo.getResult()) ? queInfo.getResult() : "";
buffer.append("<div class="questions_wrapper_item_sq">n" +
" <div class="clearfix">n" +
" <span class="fl">")
.append(j + 1)
.append(".</span>n" +
" <div class="sq_question_structure fl">n" +
" <span class="structure_type">【答案】</span><span>")
.append(answerStr)
.append("</span>n" +
" </div>n" +
" </div>");
}
//考点:
if(info.contains("knowledge")) {
String knowPointStr = !StringUtils.isNullOrBlank(queInfo.getKnowledge()) ? this.getKnowPointStr(queInfo.getKnowledge()) : "";
buffer.append("<div class="sq_question_structure">n" +
" <span class="structure_type">【考点】</span><span>")
.append(knowPointStr)
.append("</span>n" +
" </div>");
}
//解析;
if(info.contains("analysis")) {
String analysisStr = !StringUtils.isNullOrBlank(queInfo.getAnalysis()) ? queInfo.getAnalysis() : "";
buffer.append(" <div class="sq_question_structure">n" +
" <span class="structure_type">【解析】</span><span>")
.append(analysisStr)
.append("</span></div>");
}
j++;
}
}
qq++;
}
buffer.append("</div></div>");
}
}
dataHtml =buffer.append(end).toString();
return dataHtml;
}
3.将上面处理过的dataHtml通过处理(将包含的图片转化成base64)再导出到word即可
public void exportPaperWord(HttpServletResponse response, HttpServletRequest request, String sourceData,
String fileName,String PaperType) throws BaseException {
try {
HashMap<String, Object> data = new HashMap<String, Object>();
//调用相关方法处理图片
RichHtmlHandler handler = new RichHtmlHandler(sourceData);
handler.setDocSrcLocationPrex("file:///C:/8595226D");
handler.setDocSrcParent("file3405.files");
handler.setNextPartId("01D214BC.6A592540");
handler.setShapeidPrex("_x56fe__x7247__x0020");
handler.setSpidPrex("_x0000_i");
handler.setTypeid("#_x0000_t75");
handler.handledHtml(false, staticResourcePath,PaperType);
String handledBase64Block = "";
if (handler.getDocBase64BlockResults() != null
&& handler.getDocBase64BlockResults().size() > 0) {
for (String item : handler.getDocBase64BlockResults()) {
handledBase64Block += item + "n";
}
}
data.put("imagesBase64String", handledBase64Block);
String xmlimaHref = "";
if (handler.getXmlImgRefs() != null
&& handler.getXmlImgRefs().size() > 0) {
for (String item : handler.getXmlImgRefs()) {
xmlimaHref += item + "n";
}
}
String bodyBlock = handler.getHandledDocBodyBlock();
data.put("imagesXmlHrefString", xmlimaHref);
data.put("content", bodyBlock);
Template template = WordGeneratorWithFreemarker.getTemplate("html2word.ftl");
template.setEncoding("UTF-8");
WordHtmlGeneratorHelper.handleAllObject(data);
//导出doc文件流到页面
String agent = request.getHeader("user-agent");
//附件名编码,解决中文乱码问题
try {
fileName = ExcelUtils.encodeDownloadFilename(fileName, agent);
} catch (IOException e) {
throw new Exception(ResultEnum.ENCODING_FORMAT_UNSURPORT);
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/x-download");
response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".doc");
Writer writer = response.getWriter();
template.process(data, writer);
writer.flush();
writer.close();
} catch (Exception e) {
log.error("导出word 异常,{}", e.getMessage());
throw new BaseException(ResultEnum.UNKONW_ERROR);
}
}
最后附上工具类链接: https://pan.baidu.com/s/1K6dFibIKh-fVTVJarIaBjA 提取码: eiga