一、設計出的履歷模闆圖以及給的履歷小圖示切圖

二、按照履歷模闆圖建立履歷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個。