Freemarker 模板導出(帶圖片)

1. 依賴

        <!--FreeMarker-->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>

2. 模板

  • 需要放圖片的位置,直接把圖片粘貼進去調整好大小。

    <pkg:part pkg:name="/word/media/image1.jpeg" pkg:contentType="image/jpeg">
       <pkg:binaryData>${image}</pkg:binaryData>
    </pkg:part>
    
  • doc或docx文件另存爲xml,然後將xml文件保存到項目模板位置。

  • pkg:binaryData原本的Base64編碼</pkg:binaryData>,替換爲${變量名}

3. 具體實現

  • 將需要填充的數據查詢,填充模板,本地生成,返回流給前端,瀏覽器自動下載。
   @GetMapping("/exportPersonalInformation")
    @ApiOperation("廉政檔案模板導出")
    @LogAnnotation("廉政檔案模板導出")
    public Result exportPersonalInformation(HttpServletResponse response, String oid) {
        try {
            Map<String,Object> map = personalInformationService.exportPersonalInformation(oid);
            //創建文件名稱 +String.valueOf(System.currentTimeMillis())
            String fileName = "D:\\" + File.separator + "幹部任免審批表.doc";
            String templateFileName = this.getClass().getResource("/").getPath() + "templates" + File.separator;

            //1、創建Configuration對象,傳參freemarker的版本號
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_22);
            configuration.setClassicCompatible(true);   //解決空值問題,必不可少
            configuration.setDefaultEncoding("UTF-8");
            //2、設置模板文件所在的路徑
            // configuration.setClassForTemplateLoading(this.getClass(), "E:\\workspace\\Java\\company\\cg-server-project\\enterprise-vertical\\vertical-system\\src\\main\\resources\\templates\\leader.ftl");//File.separator
            //3、設置模板文件所用的字符集,一般設置爲utf-8
            configuration.setDefaultEncoding("utf-8");
            // 設置存放路徑
            configuration.setDirectoryForTemplateLoading(new File(templateFileName));//File.separator

            //4、根據獲取到的名稱加載一個模板,獲取一個模板對象'
            Template template = configuration.getTemplate("personalInfomation.xml", "utf-8");


            //6、創建一個Writer對象,指定生成的文件名
            File outFile = new File(fileName);
            //若是路徑不存在則創建
            if (!outFile.getParentFile().exists()) {
                outFile.getParentFile().mkdirs();
            }
            Writer out = null;
            FileOutputStream fos = null;
            try {
                fos = new FileOutputStream(outFile);
                OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
                //這個地方對流的編碼不可或缺,使用main()單獨調用時,應該可以,但是如果是web請求導出時導出後word文檔就會打不開,並且包XML文件錯誤。主要是編碼格式不正確,無法解析。
                //out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile)));
                out = new BufferedWriter(oWriter);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            try {
                template.process(map, out);
                out.close();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

            response.setContentType("application/force-download");// 設置強制下載不打開
            response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode("幹部任免審批表.doc", "UTF-8"));// 設置文件名
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(outFile);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                outFile.delete();
            }

            return null;
        } catch (Exception e) {
            log.error("廉政檔案模板導出失敗", e);
            return Result.error().message("廉政檔案模板導出失敗");
        }
    }
  • 獲得圖片的base64碼(我的有解密,正常用下面的就行。

        //獲得圖片的base64碼
        public static String getImageBase(String src) throws Exception {
            if (src == null || src == "") {
                return "";
            }
            File file = new File(src);
            if (!file.exists()) {
                return "";
            }
            InputStream in = null;
            byte[] data = null;
            try {
                in = new FileInputStream(file);
                data = new byte[in.available()];
                in.read(data);
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(data);
        }
    
  • 遍歷表格我用的 stringBuffer 拼接的數據,僅供參考。

        [@Override](https://my.oschina.net/u/1162528)
        public Map<String, Object> exportPersonalInformation(String oid) throws IOException {
            HashMap<String, Object> map = new HashMap<>();
            LzdaPersonalInformation personalInformation = personalInformationMapper.selectById(oid);
            if (personalInformation != null) {
                SimpleDateFormat ymdFormat = new SimpleDateFormat("yyyy年MM月dd日");
                // 姓名
                map.put("personName", personalInformation.getPersonName());
                // 性別
                map.put("sexName", personalInformation.getSexName());
                // 出生年月
                if (personalInformation.getBirthday() != null) {
                    map.put("birthday", ymdFormat.format(personalInformation.getBirthday()));
                } else {
                    map.put("birthday", "");
                }
                // 民族
                map.put("nationName", personalInformation.getNationName());
                // 籍貫
                map.put("censusRegisterProvinceName", personalInformation.getCensusRegisterProvinceName());
                // 出生地
                map.put("birthplace", personalInformation.getBirthplace());
                // 入黨時間
                if (personalInformation.getPartyTime() != null) {
                    map.put("partyTime", ymdFormat.format(personalInformation.getPartyTime()));
                } else {
                    map.put("partyTime", "");
                }
                if (personalInformation.getWorkTime() != null) {
                    // 參加工作時間
                    map.put("workTime", ymdFormat.format(personalInformation.getWorkTime()));
                } else {
                    map.put("workTime", "");
                }
    
                // 健康狀況
                map.put("healthConditionNameOne", personalInformation.getHealthConditionNameOne());
                // 專業技術職務
                map.put("professionalTechnical", personalInformation.getProfessionalTechnical());
                // 熟悉專業有何專長
                map.put("specialSkill", personalInformation.getSpecialSkill());
                // 學歷 全日制
                map.put("allEducationBackgroundFirstName", personalInformation.getAllEducationBackgroundFirstName());
                map.put("allEducationBackgroundSecondName", personalInformation.getAllEducationBackgroundSecondName());
                // 學歷 在職教育
                map.put("inEducationBackgroundFirstName", personalInformation.getInEducationBackgroundFirstName());
                map.put("inEducationBackgroundSecondName", personalInformation.getInEducationBackgroundSecondName());
                // 全日制 畢業院校系及專業
                map.put("allEducationGraduateInstitutions", personalInformation.getAllEducationGraduateInstitutions());
                // 在職教育 畢業院校系及專業
                map.put("inEducationGraduateInstitutions", personalInformation.getInEducationGraduateInstitutions());
                // 現任職務
                map.put("presentOccupation", personalInformation.getPresentOccupation());
                // 擬任職務
                map.put("designatedPosition", personalInformation.getDesignatedPosition());
                // 擬免職務
                map.put("toFreeOccupation", personalInformation.getToFreeOccupation());
                // 簡歷
                map.put("resume", personalInformation.getResume());
                // 獎懲情況
                map.put("rewardsPunishment", personalInformation.getRewardsPunishment());
                // 年度考覈結果
                map.put("annualAssessment", personalInformation.getAnnualAssessment());
                // 任免理由
                map.put("appointReason", personalInformation.getAppointReason());
                // 家庭成員及重要社會關係
                List<LzdaFamilyRelationInfo> familyRelationInfos = familyRelationInfoMapper.selectList(Wrappers.<LzdaFamilyRelationInfo>lambdaQuery().eq(LzdaFamilyRelationInfo::getBusinessId, oid).orderByAsc(LzdaFamilyRelationInfo::getSerialNumber));
                if (CollectionUtils.isNotEmpty(familyRelationInfos)) {
                    StringBuffer family = new StringBuffer();
                    List<LzdaFamilyRelationInfo> familyList = new ArrayList<>();
                    familyList.addAll(familyRelationInfos);
                    // 不到6行添加空數據
                    if (familyRelationInfos.size() < 6) {
                        for (int i = 0; i < 7 - familyRelationInfos.size(); i++) {
                            LzdaFamilyRelationInfo lzdaFamilyRelationInfo = new LzdaFamilyRelationInfo();
                            // 稱謂
                            lzdaFamilyRelationInfo.setFamilyRelationAppellation("");
                            // 姓名
                            lzdaFamilyRelationInfo.setFamilyName("");
                            // 年齡
                            lzdaFamilyRelationInfo.setAge("");
                            // 政治面貌
                            lzdaFamilyRelationInfo.setFamilyPartyName("");
                            // 工作單位及職務
                            lzdaFamilyRelationInfo.setFamilyWorkUnit("");
                            familyList.add(lzdaFamilyRelationInfo);
                        }
                    }
                    for (LzdaFamilyRelationInfo lzdaFamilyRelationInfo : familyList) {
                        family.append("<w:tr>\n" +
                                "                            <w:tblPrEx>\n" +
                                "                                <w:tblBorders>\n" +
                                "                                    <w:top w:val=\"single\" w:color=\"auto\" w:sz=\"12\" w:space=\"0\"/>\n" +
                                "                                    <w:left w:val=\"single\" w:color=\"auto\" w:sz=\"12\" w:space=\"0\"/>\n" +
                                "                                    <w:bottom w:val=\"single\" w:color=\"auto\" w:sz=\"12\" w:space=\"0\"/>\n" +
                                "                                    <w:right w:val=\"single\" w:color=\"auto\" w:sz=\"12\" w:space=\"0\"/>\n" +
                                "                                    <w:insideH w:val=\"single\" w:color=\"auto\" w:sz=\"8\" w:space=\"0\"/>\n" +
                                "                                    <w:insideV w:val=\"single\" w:color=\"auto\" w:sz=\"8\" w:space=\"0\"/>\n" +
                                "                                </w:tblBorders>\n" +
                                "                                <w:tblCellMar>\n" +
                                "                                    <w:top w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "                                    <w:left w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "                                    <w:bottom w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "                                    <w:right w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "                                </w:tblCellMar>\n" +
                                "                            </w:tblPrEx>\n" +
                                "                            <w:trPr>\n" +
                                "                                <w:cantSplit/>\n" +
                                "                                <w:trHeight w:val=\"697\" w:hRule=\"exact\"/>\n" +
                                "                            </w:trPr>\n" +
                                "                            <w:tc>\n" +
                                "                                <w:tcPr>\n" +
                                "                                    <w:tcW w:w=\"742\" w:type=\"dxa\"/>\n" +
                                "                                    <w:vMerge w:val=\"continue\"/>\n" +
                                "                                    <w:noWrap w:val=\"0\"/>\n" +
                                "                                    <w:textDirection w:val=\"tbRlV\"/>\n" +
                                "                                    <w:vAlign w:val=\"center\"/>\n" +
                                "                                </w:tcPr>\n" +
                                "                                <w:p>\n" +
                                "                                    <w:pPr>\n" +
                                "                                        <w:spacing w:line=\"0\" w:lineRule=\"atLeast\"/>\n" +
                                "                                        <w:ind w:left=\"113\" w:right=\"113\"/>\n" +
                                "                                        <w:jc w:val=\"center\"/>\n" +
                                "                                        <w:rPr>\n" +
                                "                                            <w:rFonts w:hint=\"eastAsia\"/>\n" +
                                "                                            <w:sz w:val=\"24\"/>\n" +
                                "                                        </w:rPr>\n" +
                                "                                    </w:pPr>\n" +
                                "                                </w:p>\n" +
                                "                            </w:tc>\n" +
                                "<w:tc>\n" +
                                "    <w:tcPr>\n" +
                                "        <w:tcW w:w=\"1092\" w:type=\"dxa\"/>\n" +
                                "        <w:noWrap w:val=\"0\"/>\n" +
                                "        <w:tcMar>\n" +
                                "            <w:top w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:left w:w=\"60\" w:type=\"dxa\"/>\n" +
                                "            <w:bottom w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:right w:w=\"40\" w:type=\"dxa\"/>\n" +
                                "        </w:tcMar>\n" +
                                "        <w:vAlign w:val=\"center\"/>\n" +
                                "    </w:tcPr>\n" +
                                "    <w:p>\n" +
                                "        <w:pPr>\n" +
                                "            <w:spacing w:line=\"320\" w:lineRule=\"exact\"/>\n" +
                                "            <w:jc w:val=\"center\"/>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\" w:eastAsia=\"宋體\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "        </w:pPr>\n" +
                                "        <w:r>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "            <w:t>" + lzdaFamilyRelationInfo.getFamilyRelationAppellation() + "</w:t>\n" +
                                "        </w:r>\n" +
                                "    </w:p>\n" +
                                "</w:tc>\n" +
                                "<w:tc>\n" +
                                "    <w:tcPr>\n" +
                                "        <w:tcW w:w=\"1274\" w:type=\"dxa\"/>\n" +
                                "        <w:noWrap w:val=\"0\"/>\n" +
                                "        <w:tcMar>\n" +
                                "            <w:top w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:left w:w=\"60\" w:type=\"dxa\"/>\n" +
                                "            <w:bottom w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:right w:w=\"40\" w:type=\"dxa\"/>\n" +
                                "        </w:tcMar>\n" +
                                "        <w:vAlign w:val=\"center\"/>\n" +
                                "    </w:tcPr>\n" +
                                "    <w:p>\n" +
                                "        <w:pPr>\n" +
                                "            <w:kinsoku w:val=\"0\"/>\n" +
                                "            <w:spacing w:line=\"320\" w:lineRule=\"exact\"/>\n" +
                                "            <w:jc w:val=\"center\"/>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\" w:eastAsia=\"宋體\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "        </w:pPr>\n" +
                                "        <w:r>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "            <w:t>" + lzdaFamilyRelationInfo.getFamilyName() + "</w:t>\n" +
                                "        </w:r>\n" +
                                "    </w:p>\n" +
                                "</w:tc>\n" +
                                "<w:tc>\n" +
                                "    <w:tcPr>\n" +
                                "        <w:tcW w:w=\"574\" w:type=\"dxa\"/>\n" +
                                "        <w:noWrap w:val=\"0\"/>\n" +
                                "        <w:tcMar>\n" +
                                "            <w:top w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:left w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:bottom w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:right w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "        </w:tcMar>\n" +
                                "        <w:vAlign w:val=\"center\"/>\n" +
                                "    </w:tcPr>\n" +
                                "    <w:p>\n" +
                                "        <w:pPr>\n" +
                                "            <w:spacing w:line=\"320\" w:lineRule=\"exact\"/>\n" +
                                "            <w:jc w:val=\"center\"/>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\" w:eastAsia=\"宋體\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "        </w:pPr>\n" +
                                "        <w:r>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "            <w:t>" + lzdaFamilyRelationInfo.getAge() + "</w:t>\n" +
                                "        </w:r>\n" +
                                "    </w:p>\n" +
                                "</w:tc>\n" +
                                "<w:tc>\n" +
                                "    <w:tcPr>\n" +
                                "        <w:tcW w:w=\"1008\" w:type=\"dxa\"/>\n" +
                                "        <w:noWrap w:val=\"0\"/>\n" +
                                "        <w:tcMar>\n" +
                                "            <w:top w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:left w:w=\"60\" w:type=\"dxa\"/>\n" +
                                "            <w:bottom w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:right w:w=\"40\" w:type=\"dxa\"/>\n" +
                                "        </w:tcMar>\n" +
                                "        <w:vAlign w:val=\"center\"/>\n" +
                                "    </w:tcPr>\n" +
                                "    <w:p>\n" +
                                "        <w:pPr>\n" +
                                "            <w:spacing w:line=\"320\" w:lineRule=\"exact\"/>\n" +
                                "            <w:jc w:val=\"center\"/>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\" w:eastAsia=\"宋體\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "        </w:pPr>\n" +
                                "        <w:r>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "            <w:t>" + lzdaFamilyRelationInfo.getFamilyPartyName() + "</w:t>\n" +
                                "        </w:r>\n" +
                                "    </w:p>\n" +
                                "</w:tc>\n" +
                                "<w:tc>\n" +
                                "    <w:tcPr>\n" +
                                "        <w:tcW w:w=\"4731\" w:type=\"dxa\"/>\n" +
                                "        <w:gridSpan w:val=\"3\"/>\n" +
                                "        <w:noWrap w:val=\"0\"/>\n" +
                                "        <w:tcMar>\n" +
                                "            <w:top w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:left w:w=\"60\" w:type=\"dxa\"/>\n" +
                                "            <w:bottom w:w=\"0\" w:type=\"dxa\"/>\n" +
                                "            <w:right w:w=\"40\" w:type=\"dxa\"/>\n" +
                                "        </w:tcMar>\n" +
                                "        <w:vAlign w:val=\"center\"/>\n" +
                                "    </w:tcPr>\n" +
                                "    <w:p>\n" +
                                "        <w:pPr>\n" +
                                "            <w:spacing w:line=\"320\" w:lineRule=\"exact\"/>\n" +
                                "            <w:jc w:val=\"left\"/>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\" w:eastAsia=\"宋體\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "        </w:pPr>\n" +
                                "        <w:r>\n" +
                                "            <w:rPr>\n" +
                                "                <w:rFonts w:hint=\"eastAsia\"/>\n" +
                                "                <w:szCs w:val=\"28\"/>\n" +
                                "                <w:lang w:val=\"en-US\" w:eastAsia=\"zh-CN\"/>\n" +
                                "            </w:rPr>\n" +
                                "            <w:t>" + lzdaFamilyRelationInfo.getFamilyWorkUnit() + "</w:t>\n" +
                                "        </w:r>\n" +
                                "    </w:p>\n" +
                                "</w:tc>" +
                                "</w:tr>");
                    }
                    map.put("family", family);
                }
                // 呈報單位
                map.put("regionName", SessionUtils.getRegionName());
                map.put("date", ymdFormat.format(new Date()));
                // 填表人
                map.put("preparer", SessionUtils.getUserName());
                // 圖片
                MultiMediaInfo multiMediaInfo = multiMediaInfoMapper.selectOne(Wrappers.<MultiMediaInfo>lambdaQuery().eq(MultiMediaInfo::getBusinessOid, oid));
                // 解密圖片文件,並生成64編碼
                if (multiMediaInfo != null) {
                    byte[] decrypt = MultiMediaUtils.decrypt(multiMediaConfig.getProfile(), multiMediaInfo.getFilePath(), multiMediaConfig.getSecretKey());
                    BASE64Encoder encoder = new BASE64Encoder();
                    if (decrypt != null) {
                        map.put("image", encoder.encode(decrypt));
                    } else {
                        map.put("image", "");
                    }
                }
            }
            return map;
        }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章