一、接口
@RequestMapping("/export")
public void exportPdf(@RequestParam String tId, HttpServletResponse response) throws Exception {
System.out.println("==================开始导出======================");
ByteArrayOutputStream baos = null;
OutputStream out = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
try {
// 模板中的数据,实际运用从数据库中查询
Map<String, Object> data = new HashMap<>();
//查询人才信息 并且添加到集合中
List<RlTalentEntity> talentEntityList = rlTalentService.list(new QueryWrapper<RlTalentEntity>().eq("t_id", tId));
List<Map<String, String>> mapListTalent = new ArrayList<>();
Map<String, String> mapTalent;
for (RlTalentEntity dict : talentEntityList) {
String gender = dict.getGender();
if (gender.equals("44")) {
gender = "男";
} else if (gender.equals("45")) {
gender = "女";
} else {
gender = "保密";
}
// 转换日期格式
String bornDate = sdf.format(dict.getBornDate());
mapTalent = new HashMap<>();
mapTalent.put("name", dict.getName());
mapTalent.put("Contact", dict.getContact());
mapTalent.put("EmailAddress", dict.getEmailAddress());
mapTalent.put("Gender", gender);
mapTalent.put("BornDate", bornDate);
mapTalent.put("WorkExperience", dict.getWorkExperience());
mapTalent.put("ExpectedPosition", dict.getExpectedPosition());
mapTalent.put("ExpectedSalary", dict.getExpectedSalary());
mapTalent.put("PersonalAdvantage", dict.getPersonalAdvantage());
mapListTalent.add(mapTalent);
}
data.put("talentEntityList", mapListTalent);
//查询工作经历 并且添加到集合中
List<RlWorkExperienceEntity> workExperience = rlWorkExperienceService.list(new QueryWrapper<RlWorkExperienceEntity>().eq("t_id", tId));
List<Map<String, String>> mapList = new ArrayList<>();
Map<String, String> map;
for (RlWorkExperienceEntity dict : workExperience) {
// 转换日期格式为:yyyy-MM
String workingTime = sdf.format(dict.getWorkingTime());
String departuerTime = sdf.format(dict.getDepartureTime());
map = new HashMap<>();
map.put("CompanyName", dict.getCompanyName());
map.put("Position", dict.getPosition());
map.put("WorkContent", dict.getWorkContent());
map.put("WorkResults", dict.getWorkResults());
map.put("WorkingTime", workingTime);
map.put("DepartureTime", departuerTime);
mapList.add(map);
}
data.put("workExperience", mapList);
//查询教育经历 并且添加到集合中
List<RlEducationExperienceEntity> educationExperienceEntities = educationExperienceService.list(new QueryWrapper<RlEducationExperienceEntity>().eq("t_id", tId));
List<Map<String, String>> educationExperience = new ArrayList<>();
Map<String, String> map1;
for (RlEducationExperienceEntity dict : educationExperienceEntities) {
// 转换日期格式
String startTime = sdf.format(dict.getStartTime());
String overTime = sdf.format(dict.getOverTime());
map1 = new HashMap<>();
map1.put("SchoolName", dict.getSchoolName());
map1.put("EducationBackground", dict.getEducationBackground());
map1.put("StartTime", startTime);
map1.put("OverTime", overTime);
map1.put("Professional", dict.getProfessional());
map1.put("SchoolExperience", dict.getSchoolExperience());
educationExperience.add(map1);
}
data.put("educationExperienceEntities", educationExperience);
//查询项目经历
List<RlProjectExperienceEntity> experienceEntityList = projectExperienceService.list(new QueryWrapper<RlProjectExperienceEntity>().eq("t_id", tId));
List<Map<String, String>> mapList2 = new ArrayList<>();
Map<String, String> map2;
for (RlProjectExperienceEntity dict : experienceEntityList) {
//转换日期时间
String projectStartTime = sdf.format(dict.getProjectStartTime());
String projectOverTime = sdf.format(dict.getProjectOverTime());
map2 = new HashMap<>();
map2.put("ProjectName", dict.getProjectName());
map2.put("ProjectRole", dict.getProjectRole());
map2.put("ProjectStartTime", projectStartTime);
map2.put("ProjectOverTime", projectOverTime);
map2.put("ProjectDescribe", dict.getProjectDescribe());
map2.put("ProjectResults", dict.getProjectResults());
mapList2.add(map2);
}
data.put("experienceEntityList", mapList2);
baos = PDFTemplateUtil.createPDF(data, "pdf.ftl");
// 设置响应消息头,告诉浏览器当前响应是一个下载文件
response.setContentType("application/x-msdownlFoad");
List<RlTalentEntity> list = rlTalentService.list(new QueryWrapper<RlTalentEntity>().eq("t_id", tId));
String name = null;
for (RlTalentEntity rl : list) {
name = rl.getName();
}
// 告诉浏览器,当前响应数据要求用户干预保存到文件中,以及文件名是什么 如果文件名有中文,必须URL编码
String fileName = URLEncoder.encode(name + ".pdf", "utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
out = response.getOutputStream();
baos.writeTo(out);
baos.close();
System.out.println("==================导出成功" + fileName + "======================");
} catch (Exception e) {
e.printStackTrace();
throw new Exception("导出失败:" + e.getMessage());
} finally {
if (baos != null) {
baos.close();
}
if (out != null) {
out.close();
}
}
}
二、PDF工具类
public class PDFTemplateUtil {
/**
* 通过模板导出pdf文件
* @param data 数据
* @param templateFileName 模板文件名
* @throws Exception
*/
public static ByteArrayOutputStream createPDF(Map<String,Object> data, String templateFileName) throws Exception {
// 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例
Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
// 指定FreeMarker模板文件的位置
cfg.setClassForTemplateLoading(PDFTemplateUtil.class,"/templates/");
ITextRenderer renderer = new ITextRenderer();
OutputStream out = new ByteArrayOutputStream();
try {
// 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示
renderer.getFontResolver().addFont("/templates/font/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// 设置模板的编码格式
cfg.setEncoding(Locale.CHINA, "UTF-8");
// 获取模板文件
Template template = cfg.getTemplate(templateFileName, "UTF-8");
StringWriter writer = new StringWriter();
// 将数据输出到html中
template.process(data, writer);
writer.flush();
String html = writer.toString();
// 把html代码传入渲染器中
renderer.setDocumentFromString(html);
// 设置模板中的图片路径 (这里的images在resources目录下) 模板中img标签src路径需要相对路径加图片名 如<img src="images/xh.jpg"/>
// String url = PDFTemplateUtil.class.getClassLoader().getResource("images").toURI().toString();
// renderer.getSharedContext().setBaseURL(url);
renderer.layout();
renderer.createPDF(out, false);
renderer.finishPDF();
out.flush();
return (ByteArrayOutputStream)out;
} finally {
if(out != null){
out.close();
}
}
}
}
注意:SIMSUN.TTC文件来自自己计算机C:\WINDOWS\Fonts文件夹里面的宋体,要大写
xxx.ftl模板文件代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
<style>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
font-family: SimSun;
}
section{
display:block;
margin: 20px 10px;
}
.title{
text-align: center;
}
.preface p{
line-height: 30px;
}
.preface p.content{
text-indent: 2em;
}
section > table{
table-layout: fixed;
width: 100%;
margin: 20px 0px;
text-align:center;
word-wrap:break-word;
}
section table td{
padding:5px 0px;
}
</style>
</head>
<body>
<!-- 个人信息 start -->
<section class="title">
<#-- 遍历-->
<#list talentEntityList as talent>
<h3>${talent.name}</h3>
<span>联系电话:${talent.Contact}</span> <span>邮箱:${talent.EmailAddress}</span> <span>性别:${talent.Gender}</span> <span>出生日期:${talent.BornDate}</span> <br/>
<span>所在城市:深圳</span> <span>工作经验:${talent.WorkExperience}</span> <span>求职意向:${talent.ExpectedPosition}</span> <span>期望薪资:${talent.ExpectedSalary}</span>
<span></span>
</#list>
</section>
<!-- 个人信息 end -->
<!-- 个人优势 start -->
<section class="preface">
<h4>个人优势</h4>
<hr/>
<#list talentEntityList as persona>${persona.PersonalAdvantage}</#list>
</section>
<!-- 个人优势 end -->
<!-- 工作经验 end -->
<section class="preface">
<h4>工作经验</h4>
<hr/>
<#list workExperience as ad>
<span>${ad.WorkingTime}-${ad.DepartureTime}</span>
<span>${ad.CompanyName}</span>
<span>${ad.Position}</span><br/>
<span>内容:${ad.WorkContent}</span><br/>
<span>业绩:${ad.WorkResults}</span><br/><br/>
</#list>
</section>
<!-- 工作经验 end -->
<!-- 项目经历 end -->
<section class="preface">
<h4>项目经历</h4>
<hr/>
<#list experienceEntityList as experience>
<span>${experience.ProjectStartTime}-${experience.ProjectOverTime}</span>
<span>${experience.ProjectName}</span>
<span>${experience.ProjectRole}</span><br/>
<span>项目描述:${experience.ProjectDescribe}</span><br/>
<span>项目业绩:${experience.ProjectResults}</span><br/><br/>
</#list>
</section>
<!-- 项目经历 end -->
<!-- 教育经历 end -->
<section class="preface">
<h4>教育经历</h4>
<hr/>
<#list educationExperienceEntities as ab>
<span>${ab.SchoolName}</span>
<span>${ab.EducationBackground}</span>
<span>${ab.StartTime}-${ab.OverTime}</span><br/>
<span>专业:${ab.Professional}</span><br/>
<span>学校经历:${ab.SchoolExperience}</span><br/><br/>
</#list>
</section>
<!-- 教育经历 end -->
</body>
</html>
vue 前端代码