xiatian 5 yıl önce
ebeveyn
işleme
7bbb9ba107

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

@@ -1,7 +1,10 @@
 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;
@@ -10,6 +13,8 @@ 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;
@@ -44,700 +49,731 @@ 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 (("div".equals(e.nodeName())||"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(),
-                    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 (("div".equals(e.nodeName()) || "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));
+					
+					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());
+				se.getParam().setWidth(ImageOne.getWidth());
+			} 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);
+		}
+	}
 
 }