项目场景:
具体场景在上一篇的开头已经说明:【笔记】响应表头中的Content-disposition_苗老八的博客-优快云博客
问题描述
简单来说就是我在后台已经生成了PDF文件,但是需要再加一个预览功能,而不是直接下载,于是我通过上一篇描述了Content-disposition 响应头方式开始着手,一通捣鼓没捣鼓出来,在我准备放弃的时候,发现之前多加了一个参数,去掉之后就能使用预览了。
解决方案:
后台代码controller:
/**
* 预览校友数据
*/
/*@RequiresPermissions("job:stuqyxx:export")*/
@ResponseBody
@RequestMapping("/createPaidanShow")
@Log(title = "预览校友数据")
public void createPaidanShow(String front_xh, HttpServletRequest request, HttpServletResponse response) throws Exception {
HashMap<String, String> map = new HashMap<>();
//根据学号去查询数据
JobXysdw jobXysdw = null;
try {
jobXysdw = jobXysdwService.selectJobXysdwByXH(front_xh);
} catch (Exception e) {
e.printStackTrace();
}
if (StringUtils.isNotNull(jobXysdw)) {
String xh = front_xh;
String DWZH = jobXysdw.getDwzh();
/*Stuqyxx表所需的字段*/
map.put("Stu_QYBH", "");
//下边的大段的取值代码不再贴上 下方同理,只放一条作为参考
/*xs表所需的字段 乙方*/
HashMap<String, String> jxx = jobXsService.selectXsJobtoXH(xh);
String yxdm = String.valueOf(jxx.get("YXDM"));
String xm = jxx.get("XM");
map.put("xs_xm", xm);
/*表底部 校区*/
//先查询校区 原来的查询会出错
String xq = jobTxxxService.selectXQByYxdm(yxdm);
JobTxxx jobTxxx = jobTxxxService.selectJobTxxxByYxdm(xq);
map.put("jt_xxmc", jobTxxx.getXxmc());
/*dw表所需字段 甲方*/
//甲方数据 因为逻辑上xysdw只填写了dwmc 所以先根据dwmc去查找 而不是dwzh
HashMap<String, String> jd = null;
if (StringUtils.isNotNull(DWZH)) {
jd = JobDwService.selectXsJobtoDwzh(DWZH);
} else {
//为空 则使用dwmc
jd = JobDwService.selectXsJobtoDwmc(jobXysdw.getDwmc());
}
if (StringUtils.isNotNull(jd)) {
map.put("jd_dwmc", jd.get("DWMC"));
} else { //避免空指针
map.put("jd_dwmc", jobXysdw.getDwmc());
}
//根据编号向word导入条形码
//创建文件夹
File pathDirect = new File(path);
if (!pathDirect.exists()) {
pathDirect.mkdirs();
}
//生成条形码图片
// String JOB_IMAGE = path + "/" + Stu_QYBH1 + ".png";
// QrCodeUtil handler = new QrCodeUtil();
// handler.createtxm(Stu_QYBH1, JOB_IMAGE);
//同一张图片上传多个地方要用不同的替换符,否则就只有一个地方显示,其他地方为空
map.put("JOB_IMAGE", "");
map.put("JOB_IMAGE1", "");
map.put("JOB_IMAGE2", "");
map.put("JOB_IMAGE3", "");
//null会引起空指针
for (String key : map.keySet()) {
if (map.get(key) == null) {
map.put(key, "");
}
}
//取值结束,开始将值填到PDF中并生成
//时间戳加8位随机数
String filePrefix = System.currentTimeMillis() + "_" + (int) ((Math.random() * 9 + 1) * 10000000);
String inputUrl = resourcesPath + "printTemplate/hkyjsxys.docx";
String path2 = path + "/template/yjs/";
File pathDirectory = new File(path2);
if (!pathDirectory.exists()) {
pathDirectory.mkdirs();
}
String inputUrl_doc = path2 + filePrefix + ".doc";
String outputUrl = path2 + filePrefix + ".pdf";
//参数替换
//填充
BokeWordUtils.changWord(inputUrl, new File(inputUrl_doc), map);
// world文件转PDF
AsposeWordsUtils.doc2pdf(inputUrl_doc, new File(outputUrl));
//文件下载
File pdfFile = new File(outputUrl);
File wordFile = new File(inputUrl_doc);
if (StringUtils.isNotEmpty(outputUrl) && pdfFile.exists()) {
String xms = xm + "_协议书.pdf";
String fileName = FileUtils.setFileDownloadHeader(request, xms);
/*pdf下载与预览的区别: 根据Content-disposition后边接的参数
attachment是下载,inline是预览
如果不是预览而是下载,就把这一整块代码块复制 把下边的inline替换为attachment 再恢复下下条的注释就行
*/
response.setHeader("Content-disposition", "inline;fileName=" + fileName);
response.setContentType("application/pdf");
//刚刚就是多了这条,所以即便是inline还是会下载,注释即可 这样浏览器会自动打开而不是下载
// response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
FileInputStream in = null;
try {
in = new FileInputStream(pdfFile);
OutputStream out = response.getOutputStream();
byte[] b = new byte[512];
while ((in.read(b)) != -1) {
out.write(b);
}
out.flush();
in.close();
out.close();
//下载完毕后清理文件
wordFile.delete();
pdfFile.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
后端代码大致分为-- 取值-填充-返回 三个阶段,
前端代码 wabacus
由于前端使用了古老的wabacus框架,可能有些读者会不太明白,简要来讲,相当于a标签打开一个小窗,再调用后端的预览PDF接口,就是这么简单
总结:
技术与技术之间的差别有时很大,又有时很小,这取决于你对它们的理解程度。