xiatian 5 gadi atpakaļ
vecāks
revīzija
ac16edb2f5

+ 11 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/ImportPaperFromJsonService.java

@@ -1624,6 +1624,17 @@ public class ImportPaperFromJsonService {
      */
     private void processFill(Question question, PaperDetailUnit paperDetailUnit, ImportPaperCheck importPaperCheck,
             int subQuesNum, int errorQuesNum) throws PaperException {
+    	if(!question.getQuesBody().contains("###")) {
+    		if (importPaperCheck.getNestedHeadNumber() == 0) {
+                importPaperCheck.setErrorInfo(
+                        "[大题名称]:" + importPaperCheck.getQuesName() + "第" + errorQuesNum + "题中,题干中没有空格");
+            } else {
+                importPaperCheck.setErrorInfo("[大题名称]:" + importPaperCheck.getQuesName() + "第"
+                        + importPaperCheck.getNestedHeadNumber() + "个套题中,第" + errorQuesNum
+                        + "题中,题干中没有空格");
+            }
+            throw new PaperException(importPaperCheck.getErrorInfo());
+    	}
         // 按3个#号截取题干
         String[] quesBody = question.getQuesBody().split("###");
         String[] quesAnwser = question.getQuesAnswer().split("##");

+ 11 - 0
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/ImportPaperService.java

@@ -2092,6 +2092,17 @@ public class ImportPaperService {
      */
     public void processFill(Question question, PaperDetailUnit paperDetailUnit, ImportPaperCheck importPaperCheck,
             int subQuesNum, int errorQuesNum) throws PaperException {
+    	if(!question.getQuesBody().contains("###")) {
+    		if (importPaperCheck.getNestedHeadNumber() == 0) {
+                importPaperCheck.setErrorInfo(
+                        "[大题名称]:" + importPaperCheck.getQuesName() + "第" + errorQuesNum + "题中,题干中没有空格");
+            } else {
+                importPaperCheck.setErrorInfo("[大题名称]:" + importPaperCheck.getQuesName() + "第"
+                        + importPaperCheck.getNestedHeadNumber() + "个套题中,第" + errorQuesNum
+                        + "题中,题干中没有空格");
+            }
+            throw new PaperException(importPaperCheck.getErrorInfo());
+    	}
         // 按3个#号截取题干
         String[] quesBody = question.getQuesBody().split("###");
         String[] quesAnwser = question.getQuesAnswer().split("##");

+ 694 - 733
examcloud-core-questions-service/src/main/java/cn/com/qmth/examcloud/core/questions/service/util/ExportPaperUtil.java

@@ -1,10 +1,7 @@
 package cn.com.qmth.examcloud.core.questions.service.util;
 
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -13,8 +10,6 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.imageio.ImageIO;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -37,7 +32,6 @@ import cn.com.qmth.examcloud.core.questions.base.json.JSection;
 import cn.com.qmth.examcloud.core.questions.base.json.JsonImportUtil;
 import cn.com.qmth.examcloud.core.questions.base.json.SectionElement;
 import cn.com.qmth.examcloud.core.questions.base.json.SectionElementParams;
-import cn.com.qmth.examcloud.core.questions.base.question.enums.QuesStructType;
 import cn.com.qmth.examcloud.core.questions.dao.entity.QuesOption;
 import cn.com.qmth.examcloud.core.questions.dao.entity.Question;
 import cn.com.qmth.examcloud.core.questions.service.bean.dto.PaperDetailExp;
@@ -49,732 +43,699 @@ import sun.misc.BASE64Decoder;
 
 public class ExportPaperUtil {
 
-	private static final Logger log = LoggerFactory.getLogger(ExportPaperUtil.class);
-
-	private static final String docxBasePath = FileDisposeUtil.getDocxBasePath();
-
-	private static final int docImageSzie = 12700;
-
-	private static final String DOCX_SUFFIX = ".docx";
-
-	private static final String ZIP_SUFFIX = ".zip";
-
-	public static final String QUESOPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
-	public static final String ELEMENT_TYPE_RID = "imageId";
-
-	public static final String ELEMENT_TYPE_TEXT = "text";
-
-	public static final String ELEMENT_TYPE_IMG = "image";
-
-	private static final String ENCODING = "UTF-8";
-
-	private static Configuration config;
-
-	private static Template docSection;
-
-	private static Template examReamarkDocument;
-
-	private static Template questionSection;
-
-	private static Template paperQuesOps;
-
-	private static Template contentTypes;
-
-	private static Template document;
-
-	private static Template documentRel;
-
-	private static Pattern heightRex = Pattern.compile("height:([\\s\\S]*?)px");
-
-	private static Pattern widthRex = Pattern.compile("width:([\\s\\S]*?)px");
-	static {
-
-		config = new Configuration(Configuration.VERSION_2_3_25);
-		// 设置编码
-		config.setDefaultEncoding(ENCODING);
-		// 设置ftl模板路径
-		config.setClassForTemplateLoading(JsonImportUtil.class, "/export_template/origin_paper/");
-
-		try {
-			questionSection = config.getTemplate("question_section.ftl", ENCODING);
-			contentTypes = config.getTemplate("content_types.ftl", ENCODING);
-			document = config.getTemplate("document.ftl", ENCODING);
-			documentRel = config.getTemplate("document_rel.ftl", ENCODING);
-			paperQuesOps = config.getTemplate("question_options.ftl", ENCODING);
-			docSection = config.getTemplate("doc_section.ftl", ENCODING);
-			examReamarkDocument = config.getTemplate("exam_reamark_document.ftl", ENCODING);
-		} catch (IOException e) {
-			log.error(e.getMessage(), e);
-		}
-	}
-
-	// 考试说明word文件
-	public static File createExamRemarkDocFile(File directory, String fileName, String html) throws IOException {
-		// doc固定源文件目录
-		File docxDir = new File(docxBasePath);
-		// 将要生成的doc源文件目录
-		File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
-		docxTargetDir.mkdir();
-		// 复制docx基础文件
-		FileUtils.copyDirectory(docxDir, docxTargetDir);
-		// 处理并生成doc源文件
-		disposeExamRemark(docxTargetDir, html);
-		// 压缩docx源文件
-		File zipfile = new File(
-				docxTargetDir.getParentFile().getAbsolutePath() + File.separator + fileName + ZIP_SUFFIX);
-		FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
-		File docfile = new File(
-				docxTargetDir.getParentFile().getAbsolutePath() + File.separator + fileName + DOCX_SUFFIX);
-		// 修改压缩包为doc文件
-		zipfile.renameTo(docfile);
-		FileUtils.deleteDirectory(docxTargetDir);
-		return docfile;
-	}
-
-	private static void disposeExamRemark(File docxTargetDir, String html) throws IOException {
-		ExportTempDataDto dto = new ExportTempDataDto();
-		List<JSection> slist = null;
-		if (StringUtils.isNotBlank(html)) {
-			slist = getSections(html);
-			if (slist != null && slist.size() > 0) {
-				htmlToDoc(slist, dto);
-			}
-		}
-		// content-type
-		writeContentType(docxTargetDir, dto);
-		// document
-		writeExamRemarkDocument(docxTargetDir, slist);
-		// document-rel
-		writeDocumentRel(docxTargetDir, dto);
-		// image file
-		writeImage(docxTargetDir, dto);
-	}
-
-	private static void writeExamRemarkDocument(File docxTargetDir, List<JSection> slist) throws IOException {
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			Map<String, Object> map = new HashMap<String, Object>();
-			map.put("sections", slist);
-			examReamarkDocument.process(map, result);
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-		File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
-		FileUtils.writeStringToFile(file, result.toString(), "utf-8");
-	}
-
-	// 考试试卷
-	public static File createPaperDocFile(Long rootOrgId, PaperExp paperExp, File directory, String paperfileName,
-			ExportTemplateType templateType) throws Exception {
-		DocxTemplateBean docxTemplate = ExportTemplateUtil.getDocxTemplateBean(rootOrgId, templateType);
-		// doc固定源文件目录
-		File docxDir = new File(docxTemplate.getDocxPath());
-		// 将要生成的doc源文件目录
-		File docxTargetDir = new File(directory.getAbsolutePath() + File.separator + "docx" + File.separator);
-		docxTargetDir.mkdir();
-		// 复制docx基础文件
-		FileUtils.copyDirectory(docxDir, docxTargetDir);
-		// 处理并生成doc源文件
-		disposePaperDoc(docxTargetDir, paperExp, docxTemplate);
-		// 压缩docx源文件
-		File zipfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator
-				+ paperfileName.substring(0, paperfileName.lastIndexOf(".")) + ZIP_SUFFIX);
-		FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
-		File docfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName);
-		// 修改压缩包为doc文件
-		zipfile.renameTo(docfile);
-		FileUtils.deleteDirectory(docxTargetDir);
-		return docfile;
-
-	}
-
-	private static void disposePaperDoc(File docxTargetDir, PaperExp paperExp, DocxTemplateBean docxTemplate)
-			throws IOException {
-		ExportTempDataDto dto = new ExportTempDataDto();
-		disposePaperExamRemark(paperExp, dto);
-		if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
-			for (PaperDetailExp pde : paperExp.getPaperDetails()) {
-				dto.setSubNum(0);
-				dto.setAnswerNum(0);
-				if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
-					for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
-						Question qes = pdue.getQuestion();
-						disposePaperQuestion(qes, dto);
-					}
-				}
-			}
-		}
-
-		// header
-		writePaperHeader(docxTargetDir, paperExp.getCourseName(), docxTemplate);
-		// content-type
-		writePaperContentType(docxTargetDir, dto, docxTemplate);
-		// document
-		writePaperDocument(docxTargetDir, paperExp, docxTemplate);
-		// document-rel
-		writePaperDocumentRel(docxTargetDir, dto, docxTemplate);
-		// image file
-		writeImage(docxTargetDir, dto);
-	}
-
-	private static void writePaperHeader(File docxTargetDir, String courseName, DocxTemplateBean docxTemplate)
-			throws IOException {
-		Template head = docxTemplate.getHeader();
-		if (head == null) {
-			return;
-		}
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("courseName", courseName);
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			head.process(map, result);
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-		File file = new File(docxTargetDir.getAbsolutePath() + "/word/header1.xml");
-		FileUtils.writeStringToFile(file, result.toString(), "utf-8");
-	}
-
-	private static void writePaperDocument(File docxTargetDir, PaperExp paperExp, DocxTemplateBean docxTemplate)
-			throws IOException {
-		String doc = getPaperDocumentDoc(paperExp, docxTemplate);
-		File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
-		FileUtils.writeStringToFile(file, doc, "utf-8");
-	}
-
-	private static String getPaperDocumentDoc(Object paperExp, DocxTemplateBean docxTemplate) {
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			docxTemplate.getDocument().process(paperExp, result);
-			return result.toString();
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
-
-	private static void writePaperContentType(File docxTargetDir, ExportTempDataDto dto, DocxTemplateBean docxTemplate)
-			throws IOException {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("images", dto.getTypes());
-		String doc = getPaperContentTypesDoc(map, docxTemplate);
-		File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
-		FileUtils.writeStringToFile(file, doc, "utf-8");
-	}
-
-	private static String getPaperContentTypesDoc(Map<String, Object> map, DocxTemplateBean docxTemplate) {
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			docxTemplate.getContentTypes().process(map, result);
-			return result.toString();
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
-
-	private static void writePaperDocumentRel(File docxTargetDir, ExportTempDataDto dto, DocxTemplateBean docxTemplate)
-			throws IOException {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("images", dto.getImages());
-		String doc = getPaperDocumentRelDoc(map, docxTemplate);
-		File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
-		FileUtils.writeStringToFile(file, doc, "utf-8");
-	}
-
-	private static String getPaperDocumentRelDoc(Map<String, Object> map, DocxTemplateBean docxTemplate) {
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			docxTemplate.getDocumentRels().process(map, result);
-			return result.toString();
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
-
-	// 原始试卷
-	public static File createOriginPaperDocFile(PaperExp paperExp, File directory) throws Exception {
-		// doc固定源文件目录
-		File docxDir = new File(docxBasePath);
-		// 将要生成的doc源文件目录
-		File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
-		docxTargetDir.mkdir();
-		// 复制docx基础文件
-		FileUtils.copyDirectory(docxDir, docxTargetDir);
-		// 处理并生成doc源文件
-		dispose(docxTargetDir, paperExp);
-		// 压缩docx源文件
-		String paperfileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_" + ExamFileType.PAPER.getName();
-		File zipfile = new File(
-				docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName + ZIP_SUFFIX);
-		FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
-		File docfile = new File(
-				docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName + DOCX_SUFFIX);
-		// 修改压缩包为doc文件
-		zipfile.renameTo(docfile);
-		FileUtils.deleteDirectory(docxTargetDir);
-		return docfile;
-
-	}
-
-	private static List<JSection> getSections(String html) {
-		return getSections(html, false);
-	}
-
-	private static List<JSection> getSections(String html, boolean diposeFillBlank) {
-		if (StringUtils.isBlank(html)) {
-			return null;
-		}
-		html = html.trim();
-		if (!html.startsWith("<p>")) {
-			html = "<p>" + html + "</p>";
-		}
-		List<JSection> ss = new ArrayList<JSection>();
-		Document doc = Jsoup.parse(html);
-		Element b = doc.body();
-		for (Node e : b.childNodes()) {
-//			if (("table".equals(e.nodeName()) ||"div".equals(e.nodeName()) || "p".equals(e.nodeName())) && e.childNodeSize() > 0) {
-			if (e.childNodeSize() > 0) {
-				JSection s = new JSection();
-				List<SectionElement> ses = new ArrayList<SectionElement>();
-				s.setElements(ses);
-				for (Node ce : e.childNodes()) {
-					getSectionElement(ce, ses, diposeFillBlank);
-				}
-				ss.add(s);
-			}
-		}
-		return ss;
-
-	}
-
-	private static void getSectionElement(Node ce, List<SectionElement> ses, boolean diposeFillBlank) {
-		if ("span".equals(ce.nodeName()) && ce.childNodeSize() > 0) {
-			for (Node e : ce.childNodes()) {
-				getSectionElement(e, ses, diposeFillBlank);
-			}
-		} else {
-			SectionElement se = new SectionElement();
-			if (ce instanceof TextNode) {
-				TextNode tn = (TextNode) ce;
-				se.setType(ELEMENT_TYPE_TEXT);
-				String text = tn.text();
-				if (diposeFillBlank) {
-					text = text.replaceAll("###", "______").replaceAll("##", "______");
-				}
-				text = text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;")
-						.replaceAll("\u0000", " ");
-				se.setValue(text);
-			} else if (ce instanceof Element) {
-				if ("img".equals(ce.nodeName())) {
-					se.setType(ELEMENT_TYPE_IMG);
-					se.setValue(ce.attr("src"));
-					SectionElementParams sep = se.getParam();
-					sep.setHeight(getHeight(ce));
-					sep.setWidth(getWidth(ce));
-
-					setImageSizeForNone(se);
-				} else {
-					Element el = (Element) ce;
-					se.setType(ELEMENT_TYPE_TEXT);
-					se.setValue(el.text());
-				}
-			}
-			ses.add(se);
-		}
-	}
-
-	private static void setImageSizeForNone(SectionElement se) {
-		if (se.getParam().getHeight() == 0 || se.getParam().getWidth() == 0) {
-			String base64 = se.getValue().substring(se.getValue().indexOf(",") + 1);
-			InputStream in = null;
-			try {
-				byte[] decoderBytes = new BASE64Decoder().decodeBuffer(base64);
-				in = new ByteArrayInputStream(decoderBytes);
-
-				BufferedImage ImageOne = ImageIO.read(in);
-				// 可以获得宽和高了
-				se.getParam().setHeight(ImageOne.getHeight() * docImageSzie);
-				se.getParam().setWidth(ImageOne.getWidth() * docImageSzie);
-			} catch (IOException e) {
-				throw new ExamCloudRuntimeException(e);
-			} finally {
-				if (in != null) {
-					try {
-						in.close();
-					} catch (IOException e) {
-					}
-				}
-			}
-
-		}
-	}
-
-	private static int getWidth(Node ce) {
-		String str = ce.attr("width");
-		if (StringUtils.isNoneBlank(str)) {
-			return getWordImgSize(str);
-		}
-		String style = ce.attr("style");
-		if (StringUtils.isNoneBlank(style)) {
-			Matcher m = widthRex.matcher(style);
-			if (m.find()) {
-				return Integer.valueOf(m.group(1)) * docImageSzie;
-			}
-		}
-		return 0;
-	}
-
-	private static int getHeight(Node ce) {
-		String str = ce.attr("height");
-		if (StringUtils.isNoneBlank(str)) {
-			return getWordImgSize(str);
-		}
-		String style = ce.attr("style");
-		if (StringUtils.isNoneBlank(style)) {
-			Matcher m = heightRex.matcher(style);
-			if (m.find()) {
-				return Integer.valueOf(m.group(1)) * docImageSzie;
-			}
-		}
-		return 0;
-	}
-
-	private static Integer getWordImgSize(String px) {
-		if (StringUtils.isBlank(px)) {
-			return null;
-		}
-		String sizeStr = px.replace("px", "");
-		Integer size = Integer.valueOf(sizeStr) * docImageSzie;
-		return size;
-	}
-
-	private static void dispose(File docxTargetDir, PaperExp paperExp) throws IOException {
-		ExportTempDataDto dto = new ExportTempDataDto();
-		if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
-			for (PaperDetailExp pde : paperExp.getPaperDetails()) {
-				dto.setMainNum(dto.getMainNum() + 1);
-				dto.setSubNum(0);
-				if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
-					for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
-						Question qes = pdue.getQuestion();
-						disposeQuestion(qes, dto);
-					}
-				}
-			}
-		}
-		// content-type
-		writeContentType(docxTargetDir, dto);
-		// document
-		writeDocument(docxTargetDir, paperExp);
-		// document-rel
-		writeDocumentRel(docxTargetDir, dto);
-		// image file
-		writeImage(docxTargetDir, dto);
-	}
-
-	private static void writeImage(File docxTargetDir, ExportTempDataDto dto) throws IOException {
-		for (SectionElement se : dto.getImages()) {
-			File file = new File(docxTargetDir.getAbsolutePath() + "/word/media/image" + se.getParam().getIndex() + "."
-					+ se.getParam().getType());
-			String base64 = se.getValue();
-			if (base64.contains("data:image")) {
-				base64 = base64.substring(base64.indexOf(",") + 1);
-			}
-			BASE64Decoder decoder = new BASE64Decoder();
-			byte[] bytes = decoder.decodeBuffer(base64);
-			FileUtils.writeByteArrayToFile(file, bytes);
-		}
-	}
-
-	private static void writeDocumentRel(File docxTargetDir, ExportTempDataDto dto) throws IOException {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("images", dto.getImages());
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			documentRel.process(map, result);
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-		File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
-		FileUtils.writeStringToFile(file, result.toString(), "utf-8");
-	}
-
-	private static void writeContentType(File docxTargetDir, ExportTempDataDto dto) throws IOException {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("images", dto.getTypes());
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			contentTypes.process(map, result);
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-		File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
-		FileUtils.writeStringToFile(file, result.toString(), "utf-8");
-	}
-
-	private static void writeDocument(File docxTargetDir, PaperExp paperExp) throws IOException {
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			document.process(paperExp, result);
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-		File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
-		FileUtils.writeStringToFile(file, result.toString(), "utf-8");
-	}
-
-	private static void disposeQuestion(Question qes, ExportTempDataDto dto) {
-		if (qes != null) {
-			List<JSection> slist1 = getSections(qes.getQuesBody(),
-					QuesStructType.FILL_BLANK_QUESTION.equals(qes.getQuestionType()));
-			if (slist1 != null && slist1.size() > 0) {
-				if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
-					dto.setSubNum(dto.getSubNum() + 1);
-					SectionElement se = new SectionElement();
-					se.setType(ELEMENT_TYPE_TEXT);
-					se.setValue(dto.getSubNum() + ".");
-					slist1.get(0).getElements().add(0, se);
-				}
-
-				htmlToDoc(slist1, dto);
-				qes.setQuesBodyWord(getQuestionDoc(slist1));
-			}
-
-			if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
-				int index = 0;
-				for (QuesOption qo : qes.getQuesOptions()) {
-					List<JSection> slist2 = getSections(qo.getOptionBody());
-					if (slist2 != null && slist2.size() > 0) {
-						SectionElement se = new SectionElement();
-						se.setType(ELEMENT_TYPE_TEXT);
-						se.setValue(QUESOPS.charAt(index) + ".");
-						index++;
-						slist2.get(0).getElements().add(0, se);
-						htmlToDoc(slist2, dto);
-						qo.setOptionBodyWord(getQuestionDoc(slist2));
-					}
-
-				}
-			}
-			List<JSection> slist3 = getSections(qes.getQuesAnswer());
-			if (slist3 != null && slist3.size() > 0) {
-				SectionElement se = new SectionElement();
-				se.setType(ELEMENT_TYPE_TEXT);
-				se.setValue("[答案]:");
-				slist3.get(0).getElements().add(0, se);
-
-				htmlToDoc(slist3, dto);
-				qes.setQuesAnswerWord(getQuestionDoc(slist3));
-			}
-
-			if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
-				dto.setSubNum(0);
-				for (Question sunqes : qes.getSubQuestions()) {
-					disposeQuestion(sunqes, dto);// 递归处理套题
-				}
-			}
-		}
-	}
-
-	private static void disposePaperExamRemark(PaperExp paperExp, ExportTempDataDto dto) {
-		if (StringUtils.isNotBlank(paperExp.getExamRemark())) {
-			List<JSection> slist = getSections(paperExp.getExamRemark());
-			if (slist != null && slist.size() > 0) {
-				htmlToDoc(slist, dto);
-				paperExp.setExamRemarkWord(getSectionDoc(slist));
-			}
-		}
-		if (paperExp.getExamRemarkWord() == null) {
-			paperExp.setExamRemarkWord("");
-		}
-	}
-
-	private static void disposePaperQuestion(Question qes, ExportTempDataDto dto) {
-		if (qes != null) {
-			if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
-				dto.setSubNum(dto.getSubNum() + 1);
-			}
-			List<JSection> slist1 = getSections(qes.getQuesBody(), true);
-			if (slist1 != null && slist1.size() > 0) {
-				if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
-					SectionElement se = new SectionElement();
-					se.setType(ELEMENT_TYPE_TEXT);
-					se.setValue(dto.getSubNum() + ".");
-					slist1.get(0).getElements().add(0, se);
-				}
-
-				htmlToDoc(slist1, dto);
-				qes.setQuesBodyWord(getQuestionDoc(slist1));
-			}
-
-			if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
-				int index = 0;
-				JOptionDto joDto = new JOptionDto();
-				List<JOption> ops = new ArrayList<JOption>();
-				joDto.setOptions(ops);
-				for (QuesOption qo : qes.getQuesOptions()) {
-					List<JSection> slist2 = getSections(qo.getOptionBody());
-					if (slist2 != null && slist2.size() > 0) {
-						SectionElement se = new SectionElement();
-						se.setType(ELEMENT_TYPE_TEXT);
-						se.setValue(QUESOPS.charAt(index) + ".");
-						index++;
-						slist2.get(0).getElements().add(0, se);
-						htmlToDoc(slist2, dto);
-						JOption jo = new JOption();
-						jo.setJsections(slist2);
-						ops.add(jo);
-					}
-				}
-				disposeQuesOptions(joDto);// 处理选项列数
-				qes.setQuesOptionsWord(getPaperQuestionDoc(joDto.getOptions()));
-			}
-			if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题不加答案序号
-				dto.setAnswerNum(dto.getAnswerNum() + 1);
-			}
-			List<JSection> slist3 = getSections(qes.getQuesAnswer());
-			if (slist3 != null && slist3.size() > 0) {
-				SectionElement se = new SectionElement();
-				se.setType(ELEMENT_TYPE_TEXT);
-				se.setValue(dto.getAnswerNum() + ".");
-				slist3.get(0).getElements().add(0, se);
-
-				htmlToDoc(slist3, dto);
-				qes.setQuesAnswerWord(getQuestionDoc(slist3));
-			}
-
-			if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
-				dto.setSubNum(0);
-				dto.setAnswerNum(0);
-				for (Question sunqes : qes.getSubQuestions()) {
-					disposePaperQuestion(sunqes, dto);// 递归处理套题
-				}
-			}
-		}
-	}
-
-	private static void disposeQuesOptions(JOptionDto joDto) {
-		for (JOption jo : joDto.getOptions()) {
-			if (jo.getJsections().size() > 1) {
-				return;
-			}
-			for (JSection js : jo.getJsections()) {
-				for (SectionElement se : js.getElements()) {
-					if (ELEMENT_TYPE_IMG.equals(se.getType())) {
-						return;
-					}
-				}
-			}
-		}
-		int columns = 4;
-		for (JOption jo : joDto.getOptions()) {
-			JSection js = jo.getJsections().get(0);
-			for (SectionElement se : js.getElements()) {
-				String text = StringEscapeUtils.unescapeXml(se.getValue());
-				if (text.length() > 20) {
-					return;
-				} else if (text.length() > 9) {
-					columns = 2;
-				}
-			}
-
-		}
-		formatList(joDto, columns);
-	}
-
-	private static void formatList(JOptionDto joDto, int size) {
-		List<JOption> ret = new ArrayList<JOption>();
-		int count = 0;
-		for (int i = 0; i < joDto.getOptions().size(); i++) {
-			if (count == 0) {
-				JOption jo = new JOption();
-				jo.setCols(size);
-				List<JSection> temlist = new ArrayList<JSection>();
-				jo.setJsections(temlist);
-				JSection js = new JSection();
-				List<SectionElement> ses = new ArrayList<SectionElement>();
-				js.setElements(ses);
-				temlist.add(js);
-				ret.add(jo);
-			}
-			if (count != 0) {
-				joDto.getOptions().get(i).getJsections().get(0).getElements().get(0).getParam().setTab(true);
-			}
-			for (SectionElement se : joDto.getOptions().get(i).getJsections().get(0).getElements()) {
-				ret.get(ret.size() - 1).getJsections().get(0).getElements().add(se);
-			}
-			count++;
-			if (count == size) {
-				count = 0;
-			}
-		}
-		joDto.setOptions(ret);
-	}
-
-	private static void htmlToDoc(List<JSection> slist, ExportTempDataDto dto) {
-		for (JSection js : slist) {
-			for (SectionElement se : js.getElements()) {
-				if (ELEMENT_TYPE_IMG.equals(se.getType())) {
-					dto.setIndex(dto.getIndex() + 1);
-					se.getParam().setIndex(dto.getIndex());
-					se.getParam().setRid(ELEMENT_TYPE_RID + dto.getIndex());
-					se.getParam().setType(getImageType(se.getValue()));
-					dto.getTypes().add(se.getParam().getType());
-					dto.getImages().add(se);
-				}
-			}
-		}
-	}
-
-	private static String getImageType(String base64) {
-		return base64.substring(11, base64.indexOf(";"));
-	}
-
-	private static String getSectionDoc(List<JSection> sections) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("sections", sections);
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			docSection.process(map, result);
-			return result.toString();
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
-
-	private static String getQuestionDoc(List<JSection> sections) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("sections", sections);
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			questionSection.process(map, result);
-			return result.toString();
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
-
-	private static String getPaperQuestionDoc(List<JOption> options) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("options", options);
-		StringWriter result = null;
-		try {
-			result = new StringWriter();
-			paperQuesOps.process(map, result);
-			return result.toString();
-		} catch (Exception e) {
-			throw new ExamCloudRuntimeException(e);
-		}
-	}
+    private static final Logger log = LoggerFactory.getLogger(ExportPaperUtil.class);
+    
+    private static final String docxBasePath=FileDisposeUtil.getDocxBasePath();
+    
+    private static final int docImageSzie=12700;
+
+    private static final String DOCX_SUFFIX = ".docx";
+
+    private static final String ZIP_SUFFIX = ".zip";
+
+    public static final String QUESOPS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    public static final String ELEMENT_TYPE_RID = "imageId";
+
+    public static final String ELEMENT_TYPE_TEXT = "text";
+
+    public static final String ELEMENT_TYPE_IMG = "image";
+
+    private static final String ENCODING = "UTF-8";
+
+    private static Configuration config;
+
+    private static Template docSection;
+    
+    private static Template examReamarkDocument;
+
+    private static Template questionSection;
+
+    private static Template paperQuesOps;
+
+    private static Template contentTypes;
+
+    private static Template document;
+
+    private static Template documentRel;
+
+    private static Pattern heightRex = Pattern.compile("height:([\\s\\S]*?)px");
+
+    private static Pattern widthRex = Pattern.compile("width:([\\s\\S]*?)px");
+    static {
+
+        config = new Configuration(Configuration.VERSION_2_3_25);
+        // 设置编码
+        config.setDefaultEncoding(ENCODING);
+        // 设置ftl模板路径
+        config.setClassForTemplateLoading(JsonImportUtil.class, "/export_template/origin_paper/");
+
+        try {
+            questionSection = config.getTemplate("question_section.ftl", ENCODING);
+            contentTypes = config.getTemplate("content_types.ftl", ENCODING);
+            document = config.getTemplate("document.ftl", ENCODING);
+            documentRel = config.getTemplate("document_rel.ftl", ENCODING);
+            paperQuesOps = config.getTemplate("question_options.ftl", ENCODING);
+            docSection=config.getTemplate("doc_section.ftl", ENCODING);
+            examReamarkDocument=config.getTemplate("exam_reamark_document.ftl", ENCODING);
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+    //考试说明word文件
+    public static File createExamRemarkDocFile(File directory,String fileName,String html) throws IOException {
+     // doc固定源文件目录
+        File docxDir = new File(docxBasePath);
+        // 将要生成的doc源文件目录
+        File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
+        docxTargetDir.mkdir();
+        // 复制docx基础文件
+        FileUtils.copyDirectory(docxDir, docxTargetDir);
+        // 处理并生成doc源文件
+        disposeExamRemark(docxTargetDir, html);
+        // 压缩docx源文件
+        File zipfile = new File(
+                docxTargetDir.getParentFile().getAbsolutePath() + File.separator + fileName + ZIP_SUFFIX);
+        FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
+        File docfile = new File(
+                docxTargetDir.getParentFile().getAbsolutePath() + File.separator + fileName + DOCX_SUFFIX);
+        // 修改压缩包为doc文件
+        zipfile.renameTo(docfile);
+        FileUtils.deleteDirectory(docxTargetDir);
+        return docfile;
+    }
+    private static void disposeExamRemark(File docxTargetDir, String html) throws IOException {
+        ExportTempDataDto dto = new ExportTempDataDto();
+        List<JSection> slist=null;
+        if (StringUtils.isNotBlank(html)) {
+            slist = getSections(html);
+            if (slist != null && slist.size() > 0) {
+                htmlToDoc(slist, dto);
+            }
+        }
+        // content-type
+        writeContentType(docxTargetDir, dto);
+        // document
+        writeExamRemarkDocument(docxTargetDir, slist);
+        // document-rel
+        writeDocumentRel(docxTargetDir, dto);
+        // image file
+        writeImage(docxTargetDir, dto);
+    }
+    private static void writeExamRemarkDocument(File docxTargetDir, List<JSection> slist) throws IOException {
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            Map<String, Object> map = new HashMap<String, Object>();
+            map.put("sections", slist);
+            examReamarkDocument.process(map, result);
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+        File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
+        FileUtils.writeStringToFile(file, result.toString(), "utf-8");
+    }
+    // 考试试卷
+    public static File createPaperDocFile(Long rootOrgId, PaperExp paperExp, File directory, String paperfileName,
+            ExportTemplateType templateType) throws Exception {
+        DocxTemplateBean docxTemplate = ExportTemplateUtil.getDocxTemplateBean(rootOrgId, templateType);
+        // doc固定源文件目录
+        File docxDir = new File(docxTemplate.getDocxPath());
+        // 将要生成的doc源文件目录
+        File docxTargetDir = new File(directory.getAbsolutePath() + File.separator + "docx" + File.separator);
+        docxTargetDir.mkdir();
+        // 复制docx基础文件
+        FileUtils.copyDirectory(docxDir, docxTargetDir);
+        // 处理并生成doc源文件
+        disposePaperDoc(docxTargetDir, paperExp, docxTemplate);
+        // 压缩docx源文件
+        File zipfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator
+                + paperfileName.substring(0, paperfileName.lastIndexOf(".")) + ZIP_SUFFIX);
+        FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
+        File docfile = new File(docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName);
+        // 修改压缩包为doc文件
+        zipfile.renameTo(docfile);
+        FileUtils.deleteDirectory(docxTargetDir);
+        return docfile;
+
+    }
+
+    private static void disposePaperDoc(File docxTargetDir, PaperExp paperExp, DocxTemplateBean docxTemplate)
+            throws IOException {
+        ExportTempDataDto dto = new ExportTempDataDto();
+        disposePaperExamRemark(paperExp, dto);
+        if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
+            for (PaperDetailExp pde : paperExp.getPaperDetails()) {
+                dto.setSubNum(0);
+                dto.setAnswerNum(0);
+                if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
+                    for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
+                        Question qes = pdue.getQuestion();
+                        disposePaperQuestion(qes, dto);
+                    }
+                }
+            }
+        }
+        
+        // header
+        writePaperHeader(docxTargetDir, paperExp.getCourseName(), docxTemplate);
+        // content-type
+        writePaperContentType(docxTargetDir, dto, docxTemplate);
+        // document
+        writePaperDocument(docxTargetDir, paperExp, docxTemplate);
+        // document-rel
+        writePaperDocumentRel(docxTargetDir, dto, docxTemplate);
+        // image file
+        writeImage(docxTargetDir, dto);
+    }
+    
+    private static void writePaperHeader(File docxTargetDir, String courseName, DocxTemplateBean docxTemplate)
+            throws IOException {
+        Template head=docxTemplate.getHeader();
+        if(head==null) {
+            return;
+        }
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("courseName", courseName);
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            head.process(map, result);
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+        File file = new File(docxTargetDir.getAbsolutePath() + "/word/header1.xml");
+        FileUtils.writeStringToFile(file, result.toString(), "utf-8");
+    }
+
+    private static void writePaperDocument(File docxTargetDir, PaperExp paperExp, DocxTemplateBean docxTemplate)
+            throws IOException {
+        String doc = getPaperDocumentDoc(paperExp, docxTemplate);
+        File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
+        FileUtils.writeStringToFile(file, doc, "utf-8");
+    }
+
+    private static String getPaperDocumentDoc(Object paperExp, DocxTemplateBean docxTemplate) {
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            docxTemplate.getDocument().process(paperExp, result);
+            return result.toString();
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+    }
+
+    private static void writePaperContentType(File docxTargetDir, ExportTempDataDto dto, DocxTemplateBean docxTemplate)
+            throws IOException {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("images", dto.getTypes());
+        String doc = getPaperContentTypesDoc(map, docxTemplate);
+        File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
+        FileUtils.writeStringToFile(file, doc, "utf-8");
+    }
+
+    private static String getPaperContentTypesDoc(Map<String, Object> map, DocxTemplateBean docxTemplate) {
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            docxTemplate.getContentTypes().process(map, result);
+            return result.toString();
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+    }
+
+    private static void writePaperDocumentRel(File docxTargetDir, ExportTempDataDto dto, DocxTemplateBean docxTemplate)
+            throws IOException {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("images", dto.getImages());
+        String doc = getPaperDocumentRelDoc(map, docxTemplate);
+        File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
+        FileUtils.writeStringToFile(file, doc, "utf-8");
+    }
+
+    private static String getPaperDocumentRelDoc(Map<String, Object> map, DocxTemplateBean docxTemplate) {
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            docxTemplate.getDocumentRels().process(map, result);
+            return result.toString();
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+    }
+
+    // 原始试卷
+    public static File createOriginPaperDocFile(PaperExp paperExp, File directory) throws Exception {
+        // doc固定源文件目录
+        File docxDir = new File(docxBasePath);
+        // 将要生成的doc源文件目录
+        File docxTargetDir = new File(directory.getAbsolutePath() + "/docx/");
+        docxTargetDir.mkdir();
+        // 复制docx基础文件
+        FileUtils.copyDirectory(docxDir, docxTargetDir);
+        // 处理并生成doc源文件
+        dispose(docxTargetDir, paperExp);
+        // 压缩docx源文件
+        String paperfileName = paperExp.getName() + "_" + paperExp.getCourseNo() + "_" + ExamFileType.PAPER.getName();
+        File zipfile = new File(
+                docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName + ZIP_SUFFIX);
+        FileDisposeUtil.createZip(docxTargetDir.getAbsolutePath(), zipfile.getAbsolutePath());
+        File docfile = new File(
+                docxTargetDir.getParentFile().getAbsolutePath() + File.separator + paperfileName + DOCX_SUFFIX);
+        // 修改压缩包为doc文件
+        zipfile.renameTo(docfile);
+        FileUtils.deleteDirectory(docxTargetDir);
+        return docfile;
+
+    }
+
+
+    private static List<JSection> getSections(String html) {
+        return getSections(html, false);
+    }
+
+    private static List<JSection> getSections(String html, boolean diposeFillBlank) {
+        if (StringUtils.isBlank(html)) {
+            return null;
+        }
+        html = html.trim();
+        if (!html.startsWith("<p>")) {
+            html = "<p>" + html + "</p>";
+        }
+        List<JSection> ss = new ArrayList<JSection>();
+        Document doc = Jsoup.parse(html);
+        Element b = doc.body();
+        for (Node e : b.childNodes()) {
+            if ("p".equals(e.nodeName()) && e.childNodeSize() > 0) {
+                JSection s = new JSection();
+                List<SectionElement> ses = new ArrayList<SectionElement>();
+                s.setElements(ses);
+                for (Node ce : e.childNodes()) {
+                    getSectionElement(ce, ses, diposeFillBlank);
+                }
+                ss.add(s);
+            }
+        }
+        return ss;
+
+    }
+
+    private static void getSectionElement(Node ce, List<SectionElement> ses, boolean diposeFillBlank) {
+        if ("span".equals(ce.nodeName()) && ce.childNodeSize() > 0) {
+            for (Node e : ce.childNodes()) {
+                getSectionElement(e, ses, diposeFillBlank);
+            }
+        } else {
+            SectionElement se = new SectionElement();
+            if (ce instanceof TextNode) {
+                TextNode tn = (TextNode) ce;
+                se.setType(ELEMENT_TYPE_TEXT);
+                String text = tn.text();
+                if (diposeFillBlank) {
+                    text = text.replaceAll("###", "______").replaceAll("##", "______");
+                }
+                text = text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\u0000", " ");
+                se.setValue(text);
+            } else if (ce instanceof Element) {
+                if ("img".equals(ce.nodeName())) {
+                    se.setType(ELEMENT_TYPE_IMG);
+                    se.setValue(ce.attr("src"));
+                    SectionElementParams sep = se.getParam();
+                    sep.setHeight(getHeight(ce));
+                    sep.setWidth(getWidth(ce));
+                } else {
+                    Element el = (Element) ce;
+                    se.setType(ELEMENT_TYPE_TEXT);
+                    se.setValue(el.text());
+                }
+            }
+            ses.add(se);
+        }
+    }
+
+    private static int getWidth(Node ce) {
+        int n = 50;
+        String str = ce.attr("width");
+        if (StringUtils.isNoneBlank(str)) {
+            return getWordImgSize(str);
+        }
+        String style = ce.attr("style");
+        if (StringUtils.isNoneBlank(style)) {
+            Matcher m = widthRex.matcher(style);
+            if (m.find()) {
+                return Integer.valueOf(m.group(1)) * docImageSzie;
+            }
+        }
+        return n;
+    }
+
+    private static int getHeight(Node ce) {
+        int n = 50;
+        String str = ce.attr("height");
+        if (StringUtils.isNoneBlank(str)) {
+            return getWordImgSize(str);
+        }
+        String style = ce.attr("style");
+        if (StringUtils.isNoneBlank(style)) {
+            Matcher m = heightRex.matcher(style);
+            if (m.find()) {
+                return Integer.valueOf(m.group(1)) * docImageSzie;
+            }
+        }
+        return n;
+    }
+
+    private static Integer getWordImgSize(String px) {
+        if (StringUtils.isBlank(px)) {
+            return null;
+        }
+        String sizeStr = px.replace("px", "");
+        Integer size = Integer.valueOf(sizeStr) * docImageSzie;
+        return size;
+    }
+
+    private static void dispose(File docxTargetDir, PaperExp paperExp) throws IOException {
+        ExportTempDataDto dto = new ExportTempDataDto();
+        if (paperExp.getPaperDetails() != null && paperExp.getPaperDetails().size() > 0) {
+            for (PaperDetailExp pde : paperExp.getPaperDetails()) {
+                dto.setMainNum(dto.getMainNum() + 1);
+                dto.setSubNum(0);
+                if (pde.getPaperDetailUnits() != null && pde.getPaperDetailUnits().size() > 0) {
+                    for (PaperDetailUnitExp pdue : pde.getPaperDetailUnits()) {
+                        Question qes = pdue.getQuestion();
+                        disposeQuestion(qes, dto);
+                    }
+                }
+            }
+        }
+        // content-type
+        writeContentType(docxTargetDir, dto);
+        // document
+        writeDocument(docxTargetDir, paperExp);
+        // document-rel
+        writeDocumentRel(docxTargetDir, dto);
+        // image file
+        writeImage(docxTargetDir, dto);
+    }
+
+    private static void writeImage(File docxTargetDir, ExportTempDataDto dto) throws IOException {
+        for (SectionElement se : dto.getImages()) {
+            File file = new File(docxTargetDir.getAbsolutePath() + "/word/media/image" + se.getParam().getIndex() + "."
+                    + se.getParam().getType());
+            String base64 = se.getValue();
+            if (base64.contains("data:image")) {
+                base64 = base64.substring(base64.indexOf(",") + 1);
+            }
+            BASE64Decoder decoder = new BASE64Decoder();
+            byte[] bytes = decoder.decodeBuffer(base64);
+            FileUtils.writeByteArrayToFile(file, bytes);
+        }
+    }
+
+    private static void writeDocumentRel(File docxTargetDir, ExportTempDataDto dto) throws IOException {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("images", dto.getImages());
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            documentRel.process(map, result);
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+        File file = new File(docxTargetDir.getAbsolutePath() + "/word/_rels/document.xml.rels");
+        FileUtils.writeStringToFile(file, result.toString(), "utf-8");
+    }
+
+    private static void writeContentType(File docxTargetDir, ExportTempDataDto dto) throws IOException {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("images", dto.getTypes());
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            contentTypes.process(map, result);
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+        File file = new File(docxTargetDir.getAbsolutePath() + "/[Content_Types].xml");
+        FileUtils.writeStringToFile(file, result.toString(), "utf-8");
+    }
+
+    private static void writeDocument(File docxTargetDir, PaperExp paperExp) throws IOException {
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            document.process(paperExp, result);
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+        File file = new File(docxTargetDir.getAbsolutePath() + "/word/document.xml");
+        FileUtils.writeStringToFile(file, result.toString(), "utf-8");
+    }
+
+    private static void disposeQuestion(Question qes, ExportTempDataDto dto) {
+        if (qes != null) {
+            List<JSection> slist1 = getSections(qes.getQuesBody(),false);
+            if (slist1 != null && slist1.size() > 0) {
+                if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
+                    dto.setSubNum(dto.getSubNum() + 1);
+                    SectionElement se = new SectionElement();
+                    se.setType(ELEMENT_TYPE_TEXT);
+                    se.setValue(dto.getSubNum() + ".");
+                    slist1.get(0).getElements().add(0, se);
+                }
+
+                htmlToDoc(slist1, dto);
+                qes.setQuesBodyWord(getQuestionDoc(slist1));
+            }
+
+            if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
+                int index = 0;
+                for (QuesOption qo : qes.getQuesOptions()) {
+                    List<JSection> slist2 = getSections(qo.getOptionBody());
+                    if (slist2 != null && slist2.size() > 0) {
+                        SectionElement se = new SectionElement();
+                        se.setType(ELEMENT_TYPE_TEXT);
+                        se.setValue(QUESOPS.charAt(index) + ".");
+                        index++;
+                        slist2.get(0).getElements().add(0, se);
+                        htmlToDoc(slist2, dto);
+                        qo.setOptionBodyWord(getQuestionDoc(slist2));
+                    }
+
+                }
+            }
+            List<JSection> slist3 = getSections(qes.getQuesAnswer());
+            if (slist3 != null && slist3.size() > 0) {
+                SectionElement se = new SectionElement();
+                se.setType(ELEMENT_TYPE_TEXT);
+                se.setValue("[答案]:");
+                slist3.get(0).getElements().add(0, se);
+
+                htmlToDoc(slist3, dto);
+                qes.setQuesAnswerWord(getQuestionDoc(slist3));
+            }
+
+            if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
+                dto.setSubNum(0);
+                for (Question sunqes : qes.getSubQuestions()) {
+                    disposeQuestion(sunqes, dto);// 递归处理套题
+                }
+            }
+        }
+    }
+
+    private static void disposePaperExamRemark(PaperExp paperExp, ExportTempDataDto dto) {
+        if (StringUtils.isNotBlank(paperExp.getExamRemark())) {
+            List<JSection> slist = getSections(paperExp.getExamRemark());
+            if (slist != null && slist.size() > 0) {
+                htmlToDoc(slist, dto);
+                paperExp.setExamRemarkWord(getSectionDoc(slist));
+            }
+        }
+        if(paperExp.getExamRemarkWord()==null) {
+            paperExp.setExamRemarkWord("");
+        }
+    }
+
+    private static void disposePaperQuestion(Question qes, ExportTempDataDto dto) {
+        if (qes != null) {
+            if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
+                dto.setSubNum(dto.getSubNum() + 1);
+            }
+            List<JSection> slist1 = getSections(qes.getQuesBody(),true);
+            if (slist1 != null && slist1.size() > 0) {
+                if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题题干不加题号
+                    SectionElement se = new SectionElement();
+                    se.setType(ELEMENT_TYPE_TEXT);
+                    se.setValue(dto.getSubNum() + ".");
+                    slist1.get(0).getElements().add(0, se);
+                }
+
+                htmlToDoc(slist1, dto);
+                qes.setQuesBodyWord(getQuestionDoc(slist1));
+            }
+
+            if (qes.getQuesOptions() != null && qes.getQuesOptions().size() > 0) {
+                int index = 0;
+                JOptionDto joDto = new JOptionDto();
+                List<JOption> ops = new ArrayList<JOption>();
+                joDto.setOptions(ops);
+                for (QuesOption qo : qes.getQuesOptions()) {
+                    List<JSection> slist2 = getSections(qo.getOptionBody());
+                    if (slist2 != null && slist2.size() > 0) {
+                        SectionElement se = new SectionElement();
+                        se.setType(ELEMENT_TYPE_TEXT);
+                        se.setValue(QUESOPS.charAt(index) + ".");
+                        index++;
+                        slist2.get(0).getElements().add(0, se);
+                        htmlToDoc(slist2, dto);
+                        JOption jo = new JOption();
+                        jo.setJsections(slist2);
+                        ops.add(jo);
+                    }
+                }
+                disposeQuesOptions(joDto);// 处理选项列数
+                qes.setQuesOptionsWord(getPaperQuestionDoc(joDto.getOptions()));
+            }
+            if (qes.getSubQuestions() == null || qes.getSubQuestions().size() == 0) {// 套题不加答案序号
+                dto.setAnswerNum(dto.getAnswerNum() + 1);
+            }
+            List<JSection> slist3 = getSections(qes.getQuesAnswer());
+            if (slist3 != null && slist3.size() > 0) {
+                SectionElement se = new SectionElement();
+                se.setType(ELEMENT_TYPE_TEXT);
+                se.setValue(dto.getAnswerNum() + ".");
+                slist3.get(0).getElements().add(0, se);
+
+                htmlToDoc(slist3, dto);
+                qes.setQuesAnswerWord(getQuestionDoc(slist3));
+            }
+
+            if (qes.getSubQuestions() != null && qes.getSubQuestions().size() > 0) {
+                dto.setSubNum(0);
+                dto.setAnswerNum(0);
+                for (Question sunqes : qes.getSubQuestions()) {
+                    disposePaperQuestion(sunqes, dto);// 递归处理套题
+                }
+            }
+        }
+    }
+
+    private static void disposeQuesOptions(JOptionDto joDto) {
+        for (JOption jo : joDto.getOptions()) {
+            if (jo.getJsections().size() > 1) {
+                return;
+            }
+            for (JSection js : jo.getJsections()) {
+                for (SectionElement se : js.getElements()) {
+                    if (ELEMENT_TYPE_IMG.equals(se.getType())) {
+                        return;
+                    }
+                }
+            }
+        }
+        int columns = 4;
+        for (JOption jo : joDto.getOptions()) {
+            JSection js = jo.getJsections().get(0);
+            for (SectionElement se : js.getElements()) {
+                String text = StringEscapeUtils.unescapeXml(se.getValue());
+                if (text.length() > 20) {
+                    return;
+                } else if (text.length() > 9) {
+                    columns = 2;
+                }
+            }
+
+        }
+        formatList(joDto, columns);
+    }
+
+    private static void formatList(JOptionDto joDto, int size) {
+        List<JOption> ret = new ArrayList<JOption>();
+        int count = 0;
+        for (int i = 0; i < joDto.getOptions().size(); i++) {
+            if (count == 0) {
+                JOption jo = new JOption();
+                jo.setCols(size);
+                List<JSection> temlist = new ArrayList<JSection>();
+                jo.setJsections(temlist);
+                JSection js = new JSection();
+                List<SectionElement> ses = new ArrayList<SectionElement>();
+                js.setElements(ses);
+                temlist.add(js);
+                ret.add(jo);
+            }
+            if (count != 0) {
+                joDto.getOptions().get(i).getJsections().get(0).getElements().get(0).getParam().setTab(true);
+            }
+            for (SectionElement se : joDto.getOptions().get(i).getJsections().get(0).getElements()) {
+                ret.get(ret.size() - 1).getJsections().get(0).getElements().add(se);
+            }
+            count++;
+            if (count == size) {
+                count = 0;
+            }
+        }
+        joDto.setOptions(ret);
+    }
+
+    private static void htmlToDoc(List<JSection> slist, ExportTempDataDto dto) {
+        for (JSection js : slist) {
+            for (SectionElement se : js.getElements()) {
+                if (ELEMENT_TYPE_IMG.equals(se.getType())) {
+                    dto.setIndex(dto.getIndex() + 1);
+                    se.getParam().setIndex(dto.getIndex());
+                    se.getParam().setRid(ELEMENT_TYPE_RID + dto.getIndex());
+                    se.getParam().setType(getImageType(se.getValue()));
+                    dto.getTypes().add(se.getParam().getType());
+                    dto.getImages().add(se);
+                }
+            }
+        }
+    }
+
+    private static String getImageType(String base64) {
+        return base64.substring(11, base64.indexOf(";"));
+    }
+    private static String getSectionDoc(List<JSection> sections) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("sections", sections);
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            docSection.process(map, result);
+            return result.toString();
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+    }
+
+    private static String getQuestionDoc(List<JSection> sections) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("sections", sections);
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            questionSection.process(map, result);
+            return result.toString();
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+    }
+
+    private static String getPaperQuestionDoc(List<JOption> options) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("options", options);
+        StringWriter result = null;
+        try {
+            result = new StringWriter();
+            paperQuesOps.process(map, result);
+            return result.toString();
+        } catch (Exception e) {
+            throw new ExamCloudRuntimeException(e);
+        }
+    }
 
 }