一、设计出的简历模板图以及给的简历小图标切图

       

二、按照简历模板图新建简历word文件 :${字段名},同时将图片插入到word中,并将建好的word文件另存为xml文件;

  

三、直接将该xml文件重命名为.ftl文件,并用编辑器(EditPlus)打开并修改

说明:字段取值用Map来存取;

   ${pictureAddrees!"...."}    pictureAddress中存的是图片转换后的64位码,!(感叹号)表示当字段值为空时取后面的默认图片的64位码;

      集合数据循环取值形式如图所示。

四、项目pom文件中加入freemarker的依赖,将ftl文件放到resource目录下

      <!--添加freeMarker-->  <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version></dependency>

  

五、工具类代码如下:

1、createWord(Map dataMap, String templateName, String fileFullPath)   ==>  根据传入的数据、模板文件名、生成文件全路径名(带.doc)来创建word文件到磁盘;

2、createZip(String zipfullPath,String[] fileFullPaths)    ==>  用流的方式根据生成的文件路径名(带.zip)、要打包的word文件全路径名数组(带.doc)来打包zip文件到磁盘;

3、createZip(String zipfullPath,String fileFullPath,boolean isKeepDirStr)  ==> 用流的方式生成zip文件,调用compressZip()方法

   compressZip(InputStream inputStream,ZipOutputStream zip, File sourceFile, String fileName,boolean isKeepDirStr) ==> 递归压缩文件夹,被调用

  注意:当生成的zip文件为带文件夹目录级别时,调用3方法;

     当生成的zip文件为纯文件时,调用2方法。

4、downLoadFile(String fullPath, HttpServletResponse response)  ==> 用流的方式下载生成的word文件、zip文件或其他文件;

5、createFromUrl(String urlAddress,String fileFullPath) ==> 从网络地址下载文件到磁盘;

  如插入简历的图片需要从网络地址下载到磁盘,再生成base64位码,否则会失败;

  个人的一些视频信息地址、附件地址也需要从网络地址下载到磁盘,保存后再一起和简历word打包成zip文件下载。

6、getImageBase(String urlAddress,String pathAddress) ==> 生成图片的Base64位码。

  

  1 package com.hs.zp.common.utils;
  2
  3 import freemarker.template.Configuration;
  4 import freemarker.template.Template;
  5 import freemarker.template.TemplateExceptionHandler;
  6
  7 import java.io.*;
  8 import java.net.URL;
  9 import java.util.Map;
 10
 11 import javax.servlet.http.HttpServletResponse;
 12 import javax.xml.soap.Text;
 13
 14 import org.apache.commons.codec.binary.Base64;
 15 import org.apache.log4j.Logger;
 16 import org.apache.tools.zip.ZipEntry;
 17 import org.apache.tools.zip.ZipOutputStream;
 18
 19 import com.google.common.io.Files;
 20
 21 /**
 22  *
 23  * @Descript TODO (利用freemark生成word及zip)
 24  * @author yeting
 25  * @date 2019年3月19日
 26  *
 27  */
 28 public class WordUtil {
 29     public static Logger logger = Logger.getLogger(WordUtil.class);
 30
 31     /**
 32      * 生成word文件(全局可用)
 33      * @param dataMap word中需要展示的动态数据,用map集合来保存
 34      * @param templateName word模板名称,例如:test.ftl
 35      * @param fileFullPath 要生成的文件全路径
 36      */
 37     @SuppressWarnings("unchecked")
 38     public static void createWord(Map dataMap, String templateName, String fileFullPath) {
 39         logger.info("【createWord】:==>方法进入");
 40         logger.info("【fileFullPath】:==>" + fileFullPath);
 41         logger.info("【templateName】:==>" + templateName);
 42
 43         try {
 44             // 创建配置实例
 45             Configuration configuration = new Configuration();
 46             logger.info("【创建配置实例】:==>");
 47
 48             // 设置编码
 49             configuration.setDefaultEncoding("UTF-8");
 50             logger.info("【设置编码】:==>");
 51
 52             // 设置处理空值
 53             configuration.setClassicCompatible(true);
 54
 55             // 设置错误控制器
 56 //            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
 57
 58 //            String pathName = Text.class.getResource("/template").getFile();
 59 //            File templateFile = new File(pathName);
 60 //            logger.info("【pathName】:==>" + pathName);
 61 //            logger.info("【templateFile】:==>" + templateFile.getName());
 62 //            configuration.setDirectoryForTemplateLoading(templateFile);
 63
 64             // 设置ftl模板文件加载方式
 65             configuration.setClassForTemplateLoading(WordUtil.class,"/template");
 66
 67             //创建文件
 68             File file = new File(fileFullPath);
 69             // 如果输出目标文件夹不存在,则创建
 70             if (!file.getParentFile().exists()) {
 71                 file.getParentFile().mkdirs();
 72             }
 73
 74             // 将模板和数据模型合并生成文件
 75             Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
 76             // 获取模板
 77             Template template = configuration.getTemplate(templateName);
 78             // 生成文件
 79             template.process(dataMap, out);
 80
 81             // 清空缓存
 82             out.flush();
 83             // 关闭流
 84             out.close();
 85
 86         } catch (Exception e) {
 87             logger.info("【生成word文件出错】:==>" + e.getMessage());
 88             e.printStackTrace();
 89         }
 90     }
 91
 92     /**
 93      * 生成zip文件,根据文件路径不带子文件夹(全局可用)
 94      * @param zipfullPath 压缩后的zip文件全路径
 95      * @param fileFullPaths 压缩前的文件全路径数组
 96      */
 97     public static void createZip(String zipfullPath,String[] fileFullPaths) {
 98         InputStream inputStream = null;
 99         ZipOutputStream zip = null;
100
101         try {
102             zip = new ZipOutputStream(new FileOutputStream(zipfullPath));
103             zip.setEncoding("gbk");
104
105             for(String fullPath:fileFullPaths) {
106                 logger.info("【createZip:fullPath】:==>" + fullPath);
107
108                 if(StringUtil.isNullOrEmpty(fullPath)) {
109                     continue;
110                 }
111
112                 //创建文件
113                 File file = new File(fullPath);
114                 String fileName = file.getName();
115
116                 //读文件流
117                 inputStream = new BufferedInputStream(new FileInputStream(file));
118                 byte[] buffer = new byte[inputStream.available()];
119                 inputStream.read(buffer);
120                 inputStream.close();
121
122                 //将读取的文件输出到zip中
123                 zip.putNextEntry(new ZipEntry(fileName));
124                 zip.write(buffer);
125                 zip.closeEntry();
126             }
127
128         } catch (Exception e) {
129             e.printStackTrace();
130         } finally {
131             try {
132                 if (inputStream != null) {
133                     inputStream.close();
134                 }
135             } catch (Exception e) {
136                 e.printStackTrace();
137             }
138
139             try {
140                 if (zip != null) {
141                     zip.close();
142                 }
143             } catch (Exception e) {
144                 e.printStackTrace();
145             }
146
147         }
148     }
149
150     /**
151      * 生成的zip文件带子文件夹(全局可用)
152      * @param zipfullPath 压缩后的zip文件全路径
153      * @param fileFullPath 压缩前的文件全路径
154      * @param isKeepDirStr 是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
155      */
156     public static void createZip(String zipfullPath,String fileFullPath,boolean isKeepDirStr) {
157         InputStream inputStream = null;
158         ZipOutputStream zip = null;
159
160         try {
161             zip = new ZipOutputStream(new FileOutputStream(zipfullPath));
162             zip.setEncoding("gbk");
163
164             File file = new File(fileFullPath);
165
166             compressZip(inputStream,zip,file, file.getName(), isKeepDirStr);//递归压缩
167
168         } catch (Exception e) {
169             e.printStackTrace();
170         } finally {
171             try {
172                 if (inputStream != null) {
173                     inputStream.close();
174                 }
175             } catch (Exception e) {
176                 e.printStackTrace();
177             }
178
179             try {
180                 if (zip != null) {
181                     zip.close();
182                 }
183             } catch (Exception e) {
184                 e.printStackTrace();
185             }
186
187         }
188     }
189
190     /**
191      * 递归压缩方法(仅限于此类中用于压缩zip文件)
192      * @param inputStream 输入流
193      * @param zip zip输出流
194      * @param sourceFile 源文件
195      * @param fileName 文件夹名或文件名
196      * @param isKeepDirStr 是否保留原来的目录结构,true:保留目录结构; false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
197      * @throws Exception
198      */
199     private static void compressZip(InputStream inputStream,ZipOutputStream zip, File sourceFile, String fileName,boolean isKeepDirStr) throws Exception{
200         logger.info("【compressZip:sourceFile】:==>" + sourceFile.getPath());
201         logger.info("【compressZip:fileName】:==>" + fileName);
202
203         if(sourceFile.isFile()){
204             //读文件流
205             inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
206             byte[] buffer = new byte[inputStream.available()];
207             inputStream.read(buffer);
208             inputStream.close();
209
210             //将读取的文件输出到zip中
211             zip.putNextEntry(new ZipEntry(fileName));
212             zip.write(buffer);
213             zip.closeEntry();
214         } else {
215             File[] listFiles = sourceFile.listFiles();
216             if(listFiles == null || listFiles.length == 0){
217                 // 需要保留原来的文件结构时,需要对空文件夹进行处理
218                 if(isKeepDirStr){
219                     zip.putNextEntry(new ZipEntry(fileName + "/"));//空文件夹的处理
220                     zip.closeEntry();// 没有文件,不需要文件的copy
221                 }
222             }else {
223                 for (File file : listFiles) {
224                     // 判断是否需要保留原来的文件结构,注意:file.getName()前面需要带上父文件夹的名字加一斜杠,不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
225                     if (isKeepDirStr) {
226                         compressZip(inputStream,zip,file,  fileName + "/" + file.getName(),isKeepDirStr);
227                     } else {
228                         compressZip(inputStream,zip, file, file.getName(),isKeepDirStr);
229                     }
230                 }
231             }
232         }
233     }
234
235     /**
236      * 下载生成的文件(全局可用)
237      * @param fullPath 全路径
238      * @param response
239      */
240     public static void downLoadFile(String fullPath, HttpServletResponse response) {
241         logger.info("【downLoadFile:fullPath】:==>" + fullPath);
242
243         InputStream inputStream = null;
244         OutputStream outputStream = null;
245
246         try {
247             //创建文件
248             File file = new File(fullPath);
249             String fileName = file.getName();
250
251             //读文件流
252             inputStream = new BufferedInputStream(new FileInputStream(file));
253             byte[] buffer = new byte[inputStream.available()];
254             inputStream.read(buffer);
255
256             //清空响应
257             response.reset();
258             response.setCharacterEncoding("UTF-8");
259             response.setContentType("application/octet-stream; charset=utf-8");
260             // response.setContentType("application/msword");
261             response.setHeader("Content-Disposition","attachment; filename=" + new String(fileName.getBytes(), "ISO8859-1"));
262             response.setHeader("Content-Length", "" + file.length());
263
264             //写文件流
265             outputStream = new BufferedOutputStream(response.getOutputStream());
266             outputStream.write(buffer);
267             outputStream.flush();
268         } catch (Exception e) {
269             e.printStackTrace();
270         } finally {
271             try {
272                 if (outputStream != null) {
273                     outputStream.close();
274                 }
275             } catch (Exception e) {
276                 e.printStackTrace();
277             }
278             try {
279                 if (inputStream != null) {
280                     inputStream.close();
281                 }
282             } catch (Exception e) {
283                 e.printStackTrace();
284             }
285
286         }
287     }
288
289     /**
290      * 下载网络文件到本地(主要用于下载简历附件)
291      * @param urlAddress 网络url地址,为空时直接返回
292      * @param fileFullPath 文件全路径
293      */
294     public static void createFromUrl(String urlAddress,String fileFullPath) {
295         logger.info("【service:开始下载网络文件】:==> 网上文件地址:" + urlAddress + "文件保存路径:" + fileFullPath);
296
297         if(StringUtil.isNullOrEmpty(urlAddress)) {
298             return ;
299         }
300
301         DataInputStream dataInputStream = null;
302         FileOutputStream fileOutputStream =null;
303         try {
304
305             URL url = new URL(urlAddress);
306
307             dataInputStream = new DataInputStream(url.openStream());//打开网络输入流
308
309             //创建文件
310             File file = new File(fileFullPath);
311             // 如果输出目标文件夹不存在,则创建
312             if (!file.getParentFile().exists()) {
313                 file.getParentFile().mkdirs();
314             }
315
316             fileOutputStream = new FileOutputStream(file);//建立一个新的文件
317
318             byte[] buffer = new byte[1024];
319             int length;
320
321             while((length = dataInputStream.read(buffer))>0){//开始填充数据
322                 fileOutputStream.write(buffer,0,length);
323             }
324
325             fileOutputStream.flush();
326         } catch (Exception e) {
327             e.printStackTrace();
328         } finally {
329             try {
330                 if(dataInputStream!=null) {
331                     dataInputStream.close();
332                 }
333             } catch (IOException e) {
334                 e.printStackTrace();
335             }
336
337             try {
338                 if(fileOutputStream!=null) {
339                     fileOutputStream.close();
340                 }
341             } catch (IOException e) {
342                 e.printStackTrace();
343             }
344         }
345     }
346
347     /**
348      * 从网上或本地获得图片的base64码(主要用于插入生成word中的图片)
349      * @param urlAddress 网络路径,二选一,目前有问题
350      * @param pathAddress 本地路径,二选一
351      * @return 返回base64码或null
352      */
353     public static String getImageBase(String urlAddress,String pathAddress) {
354         byte[] buffer = null;
355         InputStream inputStream = null;
356         String imageCodeBase64 = null;
357
358         try {
359             if(!StringUtil.isNullOrEmpty(urlAddress)){
360                 URL url = new URL(urlAddress);
361                 inputStream = new DataInputStream(url.openStream());//打开网络输入流
362                 buffer = new byte[inputStream.available()];
363                 inputStream.read(buffer);
364             }else if(!StringUtil.isNullOrEmpty(pathAddress)){
365                 inputStream = new BufferedInputStream(new FileInputStream(new File(pathAddress)));//读文件流
366                 buffer = new byte[inputStream.available()];
367                 inputStream.read(buffer);
368             }else {
369                 return null;
370             }
371
372             imageCodeBase64 = Base64.encodeBase64String(buffer);
373 //            System.out.println(imageCodeBase64);
374         }catch (Exception e) {
375             e.printStackTrace();
376         }finally {
377             try {
378                 if(inputStream!=null) {
379                     inputStream.close();
380                 }
381             } catch (IOException e) {
382                 e.printStackTrace();
383             }
384         }
385         return imageCodeBase64;
386     }
387
388
389
390
391 }

六、调用处代码如下

 逻辑:循环开始 ==>  

      取出简历数据封装到Map中  ==>  生成word文件到磁盘 ==>  下载附件等到磁盘 ==> 将word文件、下载好的文件 的全路径名放入到路径数组中

      ==>  循环中....

    循环结束 ==>

    根据路径数组打包生成zip到磁盘 ==>

    下载zip文件 ==>

    删除原文件和zip文件,下载完毕 ==>


    1     @Transactional(rollbackFor=Exception.class)
  2     @Override
  3     public void exportWordResume(List<ResumeDelivery> resumeDeliveryList,int userId, HttpServletResponse response) throws Exception {
  4         logger.info("【service:exportWordResume】:==> 服务层请求开始");
  5
  6         String[] fileFullPaths = new String[resumeDeliveryList.size()];//文件全路径数组
  7         String[] folderFullPaths = new String[resumeDeliveryList.size()];//文件夹全路径数组
  8         String[] addUrls = new String[resumeDeliveryList.size()];//附件全路径数组
  9         String[] videoFullPaths = new String[resumeDeliveryList.size()];//视频全路径数组
 10
 11         boolean flag = false;//该批文件是否存在附件
 12         String templateName = "jlmb.ftl";//模板名称
 13         Resume resume = null;//简历
 14         Map<String, Object> map = null;//获取数据信息
 15         String fileName = null;//文件名称:应聘者姓名+应聘职位名称+简历唯一标识号+下载人ID
 16         String zipFullPath = filePath + File.separator + "小马HR_求职者简历下载_" +userId;要压缩的文件夹路径
 17         String folderFullPath = null;//子文件夹全路径
 18         String fileFullPath = null;//文件全路径
 19         String addFullPath = null;//附件全路径
 20         String addSuffix = null;//附件后缀
 21         String videoFullPath = null;//视频全路径
 22         String videoSuffix = null;//视频后缀
 23         String headImagePath = null;//头像全路径
 24
 25         String validString = null;
 26         Map<Integer,String> validMap = new HashMap<>();//简历字串 key:resumeId,value:resumeId+positionName
 27
 28         int index = 1;//简历下载数
 29         int count = 0;//循环次数
 30         for(ResumeDelivery resumeDeliveryBean:resumeDeliveryList) {
 31             count++;
 32
 33             logger.info("【service:循环投递记录】:==> " + count);
 34
 35             //判断是否重复的简历不予下载
 36             validString = resumeDeliveryBean.getResumeId() + resumeDeliveryBean.getPositionName();
 37             if(validString.equals(validMap.get(resumeDeliveryBean.getResumeId()))){
 38                 logger.info("【重复简历】:==> " + validString);
 39                 continue;
 40             }else {
 41                 validMap.put(resumeDeliveryBean.getResumeId(), validString);
 42             }
 43
 44             Assert.notNull(resumeDeliveryBean.getResumeId(), "第" + count +"份简历投递记录不存在!投递ID:" + resumeDeliveryBean.getId());
 45             resume =  resumeMapper.selectByPrimaryKey(resumeDeliveryBean.getResumeId());
 46             Assert.notNull(resume, "第" + count +"份简历不存在!投递ID:" + resumeDeliveryBean.getId());
 47
 48             //隐藏手机号
 49             if(resumeDeliveryBean.getStatus() != null
 50                     && (resumeDeliveryBean.getStatus() == 0
 51                     || resumeDeliveryBean.getStatus() == 2
 52                     || resumeDeliveryBean.getStatus() == 3)) {    //    已投递、已过期、已淘汰 ==>隐藏手机号
 53                 if(!StringUtil.isNullOrEmpty(resumeDeliveryBean.getMobile())) {
 54                     resume.setMobile(resume.getMobile().substring(0, 3) + "****" + resume.getMobile().substring(resume.getMobile().length() - 4));
 55                 }
 56             }else if(resumeDeliveryBean.getEmployStatus() != null
 57                     && (resumeDeliveryBean.getEmployStatus() == 2
 58                     || resumeDeliveryBean.getEmployStatus() == 4
 59                     || resumeDeliveryBean.getEmployStatus() == 10)) {            //    不合适、申诉中、已终止
 60                 if(!StringUtil.isNullOrEmpty(resumeDeliveryBean.getMobile())) {
 61                     resume.setMobile(resume.getMobile().substring(0, 3) + "****" + resume.getMobile().substring(resume.getMobile().length() - 4));
 62                 }
 63             }
 64
 65             fileName = resume.getHunterName() + "_" + resumeDeliveryBean.getPositionName() + "_" + resume.getId()+"_" + userId;
 66             folderFullPath = zipFullPath + File.separator + fileName;
 67             fileFullPath = folderFullPath + File.separator + fileName + ".doc";
 68             addSuffix = StringUtil.isNullOrEmpty(resume.getEnclosureAddress()) ? "" : resume.getEnclosureAddress().substring(resume.getEnclosureAddress().lastIndexOf("."));
 69             addFullPath = folderFullPath + File.separator + fileName + "_附件"+ addSuffix;
 70             videoSuffix = StringUtil.isNullOrEmpty(resume.getVideoAddress()) ? "" : resume.getVideoAddress().substring(resume.getVideoAddress().lastIndexOf("."));
 71             videoFullPath = folderFullPath + File.separator + fileName + "_个人视频"+ videoSuffix;
 72             headImagePath = folderFullPath + File.separator + fileName + "_头像.jpg";
 73
 74             WordUtil.createFromUrl(resume.getPictureAddress(), headImagePath);//先下载头像到本地,再插入到word中
 75             map = this.getResumeData(resume,headImagePath);
 76
 77             logger.info("【service:开始生成word文件】:==> 文件名:" + fileFullPath);
 78             WordUtil.createWord(map, templateName, fileFullPath);//生成word文件
 79             logger.info("【service:生成word文件 完毕】:==>");
 80
 81             FileUtil.deleteFile(headImagePath);//删除头像图片
 82
 83             WordUtil.createFromUrl(resume.getEnclosureAddress(), addFullPath);//下载附件
 84             WordUtil.createFromUrl(resume.getVideoAddress(), videoFullPath);//下载视频
 85
 86
 87             //赋值
 88             fileFullPaths[index - 1] = fileFullPath;
 89             folderFullPaths[index - 1] = folderFullPath;
 90             if(!StringUtil.isNullOrEmpty(addSuffix)) {
 91                 addUrls[index - 1] = addFullPath;
 92                 flag = true;
 93             }
 94             if(!StringUtil.isNullOrEmpty(videoSuffix)) {
 95                 videoFullPaths[index - 1] = videoFullPath;
 96                 flag = true;
 97             }
 98
 99             index++;
100             if(index == 20) {//设置最多一次下载10份简历
101                 break;
102             }
103         }
104
105         if(!flag) {
106             if(resumeDeliveryList.size()==1) {
107                 logger.info("【打包下载一】:==>");
108
109                 WordUtil.downLoadFile(fileFullPaths[0], response);//下载单个word文件
110                 FileUtil.deleteFile(fileFullPaths[0]);
111             }else {
112                 logger.info("【打包下载二】:==>");
113
114                 String zipFileFullPath = zipFullPath + ".zip";//压缩后的文件名
115
116                 WordUtil.createZip(zipFileFullPath, fileFullPaths);//生成zip不带附件不带子文件夹
117                 WordUtil.downLoadFile(zipFileFullPath, response);//下载zip文件
118
119                 FileUtil.deleteFile(zipFileFullPath);
120             }
121         }else {
122             if(resumeDeliveryList.size()==1) {
123                 logger.info("【打包下载三】:==>");
124
125                 String zipFileFullPath = folderFullPaths[0] + ".zip";//压缩后的文件名
126                 String[] newfileFullPaths = new String[]{fileFullPaths[0],addUrls[0],videoFullPaths[0]};//需要下载的文件
127
128                 WordUtil.createZip(zipFileFullPath, newfileFullPaths);//生成zip带附件不带子文件夹
129                 WordUtil.downLoadFile(zipFileFullPath, response);//下载zip文件
130             }else {
131                 logger.info("【打包下载四】:==>");
132
133                 String zipFileFullPath = zipFullPath + ".zip";;//压缩后的文件名
134
135                 WordUtil.createZip(zipFileFullPath, zipFullPath , true);//生成zip带附件
136                 WordUtil.downLoadFile(zipFileFullPath, response);//下载zip文件
137
138                 FileUtil.deleteFile(zipFileFullPath);
139             }
140         }
141
142         FileUtil.deleteFileDir(zipFullPath);
143     }
144
145     /**
146      * 简历信息转Map
147      * @param resume 简历对象
148      * @param headImagePath 头像全路径
149      * @return 返回map集合
150      * @throws Exception 出生日期转年龄可能会抛出异常
151      */
152     public Map<String, Object> getResumeData(Resume resume,String headImagePath) throws Exception{
153         Map<String, Object> map = new HashMap<>();
154         map.put(Resume.EXPORT_HUNTER_NAME, resume.getHunterName());
155         map.put(Resume.EXPORT_SEX_STR, resume.getSexStr());
156         map.put(Resume.EXPORT_AGE, AgeUtil.getAgeByBirth(resume.getDateOfBirth()) + "岁");
157         map.put(Resume.EXPORT_WORHING_LENGTH_STR, resume.getWorkingLengthStr()==null ? "" : resume.getWorkingLengthStr());
158         map.put(Resume.EXPORT_MOBILE, resume.getMobile());
159         map.put(Resume.EXPORT_CREDENTIALS, resume.getCredentials());
160         map.put(Resume.EXPORT_INTRODUCE, resume.getIntroduce());
161         map.put(Resume.EXPORT_PICTURE_ADDRESS, StringUtil.isNullOrEmpty(resume.getPictureAddress()) ? null : WordUtil.getImageBase(null, headImagePath));//头像
162
163         map.put(Resume.EXPORT_INTENTION_POSITION, resume.getIntentionPosition());
164         map.put(Resume.EXPORT_INTENTION_LOCALE_STR, resume.getIntentionLocaleStr());
165         map.put(Resume.EXPORT_SALARY_UNIT_STR, resume.getSalaryExpectation());
166         map.put(Resume.EXPORT_RESUME_STATUS_STR, resume.getResumeStatusStr());
167
168         map.put(Resume.EXPORT_STUDY_BEGIN_END_DATE, null);
169         map.put(Resume.EXPORT_GRADUATE_SCHOOL, resume.getGraduateSchool());
170         map.put(Resume.EXPORT_PROFESSION, resume.getProfession());
171         map.put(Resume.EXPORT_EDUCATIONAL_BACKGROUND_STR, resume.getEducationalBackgroundStr());
172
173         map.put(Resume.EXPORT_HONORS, resume.getHonors());
174
175         if(resume.getResumeExperience()!=null && resume.getResumeExperience().size()>0) {
176             List<Map<String,Object>> list = new ArrayList<>();
177             Map<String, Object> exprMap = null;
178             for(ResumeExperience re:resume.getResumeExperience()) {
179                 exprMap = new HashMap<>();
180                 exprMap.put(ResumeExperience.EXPORT_COMPANY_NAME, re.getCompanyName());
181                 exprMap.put(ResumeExperience.EXPORT_POSITION, re.getPosition());
182                 exprMap.put(ResumeExperience.EXPORT_WORD_DESC, re.getWorkDesc());
183                 exprMap.put(ResumeExperience.EXPORT_WORK_BEGIN_END_DATE, (re.getStartDate().replace("-", "/") + "-" + re.getEndDate().replace("-", "/")));
184                 list.add(exprMap);
185             }
186
187             map.put(Resume.EXPORT_EXPERIENCE, list);
188         }
189
190         return map;
191     }

七、从测试环境下载后的简历如下

八、过程中出现的问题:

1、模板文件路径找不到  ==> 相对路径问题,检查后解决;

2、空值字段报错或显示错误 ==> 工具类代码中已解决;或修改.ftl文件中,字段接受时设置默认值;

3、多个工作经历只显示一个 ==> 数据传值有误,检查后解决;

4、头像不显示 ==> 生成的图片的base64位码有误,工具类代码中已解决;

5、doc文件不生成 ==> 模板文件字段值有问题,检查后解决;

6、下载速度问题 ==> 目前限制只能一次下载20个。

转载于:https://www.cnblogs.com/wlxslsb/p/10622745.html

springboot中使用freemarker生成word文档并打包成zip下载(简历)相关推荐

  1. Java Web项目中使用Freemarker生成Word文档

    Web项目中生成Word文档的操作屡见不鲜,基于Java的解决方案也是很多的,包括使用Jacob.Apache POI.Java2Word.iText等各种方式,其实在从Office 2003开始,就 ...

  2. Java项目中使用Freemarker生成Word文档

    Web项目中生成Word文档的操作屡见不鲜,基于Java的解决方案也是很多的,包括使用Jacob.Apache POI.Java2Word.iText等各种方式,其实在从Office 2003开始,就 ...

  3. java web 操作word文档_Java Web项目中使用Freemarker生成Word文档

    Web项目中生成Word文档的操作屡见不鲜.基于Java的解决方式也是非常多的,包含使用Jacob.Apache POI.Java2Word.iText等各种方式,事实上在从Office 2003開始 ...

  4. (详细)如何使用Freemarker生成Word文档中的文本、图片、表格、附件?

    前言-Freemarker简单介绍 近期项目工作中需要编写大量格式相同但数据不同的Word文档,需要实现自动生成文档的效果,但是通过网上冲浪和官方文档搜索,相对来说,没有分类整理的文档,因此自己抽空简 ...

  5. spring使用freemarker生成word文档包含表格、图片(循环插入)

    spring使用freemarker生成word文档包含表格.图片(循环插入) 效果图 因为测试数据是重复的,所以显示都是重复的数据,替换导入map中的数据可以显示不重复的数据. 操作步骤 1,创建一 ...

  6. 用freemarker生成word文档,并插入图片

    用freemarker生成word文档,并插入图片 最近需要做一个问卷功能,要求用户填写完问卷后,后台会生成一个word文档,将用户提交的数据插入到word中. 创建word模板 新建一个word文档 ...

  7. Java使用freemarker生成word文档并转pdf文档

    Java使用freemarker生成word文档后转pdf 先来看看效果图 进入正题 项目需求: 为订单后生成对应的pdf文档,文档内包含图片. 方案一:使用freemarker和itext把html ...

  8. 使用FreeMarker生成word文档(带图片),word转pdf,预览pdf,pdf下载工具类

    一.下载或配置: 下载jar包 :freemaker的jar包下载 下载jar包 :aspose-words的jar包下载 或者配置maven依赖: pom.xml添加aspose的依赖包(maven ...

  9. 关于FreeMarker生成word文档后转换为pdf得解决方法及常见问题

    关于FreeMarker生成word文档后转换为pdf得解决方法及常见问题 最近在做一个项目要求之前下载出的word简历直接变成pdf 格式进行展现.因为格式比较复杂,所以采用的时模板并用Freema ...

最新文章

  1. 一、javaSE (二十三)多线程
  2. Python源码学习:多线程实现机制
  3. boost::hana::span用法的测试程序
  4. 6部BBC “教材级” 地理纪录片,有生之年必看系列!
  5. 有哪些经济学理论可以用在谈恋爱上?
  6. LeetCode 1838. 最高频元素的频数(二分查找)
  7. linux 改变文件夹属性,技术|在Linux中用chattr和lsattr命令管理文件和目录属性
  8. 二叉链表之寻找两节点的最近公共祖先☆
  9. Base64编码简介及在java中的使用
  10. 西门子224XP型PLC和MCGS触摸屏控制MM420变频器
  11. docker 自定义网络
  12. 服务器抓取MIUI ota信息,官方科普|关于MIUI系统OTA
  13. 会议一体机_多媒体会议系统方案
  14. 惠普电脑u盘重装系统步骤_惠普电脑u盘重装系统xp教程
  15. 学习语言的方法,你了解几种?
  16. 打开服务器网页要5秒,网页优化技巧 如何把网页加载时间控制在1.5秒以内
  17. chrome扩展设置代理
  18. python中base64库用法详解
  19. 数据挖掘#特征工程(二)特征重要性及可解释性总结
  20. 某牛世界杯clientKey及clientSecret获取

热门文章

  1. 关于有关排课的java项目_基于jsp的选排课系统-JavaEE实现选排课系统 - java项目源码...
  2. 单片机课设:基于MSP430F249的电子时钟设计
  3. 微信小程序抓包与逆向+微信小程序反编译教程+解包教程+解包工具
  4. CVPR2020 | VSGNet:Spatial Attention Network for Detecting Human Object Interactions Using G
  5. 武林外传寻路call
  6. 基于SSM的农产品交易平台设计
  7. 联想超融合服务器安装系统,联想AIO超融合产品介绍.pdf
  8. Deep Splitting and Merging for Table Structure Decomposition 中文翻译 (表格结构识别)
  9. OCR表格识别—企业应用的技术新秀
  10. 泰斗 GPS模块调试(2)