Spring Boot + VUE 实现PDF文件的打印预览
- 导包
<!-- pdf实现 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13</version>
</dependency>
- 我是前端封装了post请求,所以这边请求类型直接使用的PostMapping。通过response返回文件流,前端解析直接加载到弹窗中
@PostMapping("/print")
public void print(@RequestBody Cld cld, HttpServletResponse response) throws Exception {
materialWeighService.print(cld, response);
}
- 制作添加PDF表单域,我的PDF模板文件存放在了项目目录中
- 下面是具体实现
@Override
public void print(Cld cld, HttpServletResponse response) throws Exception {
// 模板路径
String templatePath = "D:\\1\\2\\3\\pdfForm2.pdf";
// 生成文件名
String fileName = "resPDF";
//指定相应类型(重要)
response.setContentType("application/pdf;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;fileName="
+ URLEncoder.encode(fileName + ".pdf", "UTF-8"));
// 准备添加数据
Map<String, String> map = new HashMap<>();
map.put("流水号", cld.get流水号());
map.put("供应单位", cld.get供应单位());
map.put("承运单位", cld.get承运单位());
map.put("车牌号", cld.get车牌号());
map.put("材料类别", cld.get进场分类());
map.put("材料规格", cld.get规格());
map.put("毛重", cld.get毛重() + "");
map.put("皮重", cld.get皮重() + "");
if (cld.getHan() == null) {
map.put("含水率", "");
} else {
map.put("含水率", cld.getHan() + "");
}
String kz = cld.get暗扣重量() + cld.get扣杂重量() + "";
map.put("扣除重量", kz);
map.put("扣后净重", cld.get净重() + "");
map.put("材料产地", cld.get生产单位());
map.put("过磅员", cld.get验收人());
map.put("过毛重日期时间", cld.get时间());
map.put("回皮日期时间", cld.get回皮时间());
PdfReader reader;
OutputStream os = null;
ByteArrayOutputStream baos = null;
PdfStamper stamper;
try {
os = response.getOutputStream();
// 读取PDF模板表单
reader = new PdfReader(templatePath);
baos = new ByteArrayOutputStream();
// 根据表单生成新的PDF
stamper = new PdfStamper(reader, baos);
//获取PDF表单
AcroFields formTexts = stamper.getAcroFields();
// 设置字体(这里设置为系统字体,你也可以引入其他的字体),不设置很可能,中文无法显示。
BaseFont bf = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1",
BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
formTexts.addSubstitutionFont(bf);
// 表单赋值
for (Map.Entry<String, String> entry : map.entrySet()) {
formTexts.setField(entry.getKey(), entry.getValue());
}
//设置为true为不可更改
stamper.setFormFlattening(true);
stamper.close();
Document document = new Document();
PdfCopy copy = new PdfCopy(document, os);
document.open();
PdfImportedPage importedPage = copy.getImportedPage(new PdfReader(baos.toByteArray()), 1);
copy.addPage(importedPage);
document.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
baos.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
- VUE前端请求
- 其中service是封装的axios请求,其中要注意的是responseType参数,相应类型需指定为arraybuffer,其他类型如blob返回的文件流处理后PDF白屏,没有内容。
- 响应头类型
-
请求成功后response会返回如上的文件流
-
请求响应拦截器
-
具体实现
<!-- 打印按钮-自己去定义 -->
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
round
icon="iconfont icon-a-ziyuan4"
@click="print(scope.row)">打印</el-button>
</template>
<!-- 弹窗组件-自己去定义 -->
<print-dialog
:title="printDialog.title"
:visible="printDialog.visible"
:height="printDialog.height"
:width="printDialog.width"
@onClose="printClose()"
@onConfirm="printConfirm()">
<div slot="content">
<pdf ref="pdf" :src="pdfUrl"></pdf>
</div>
</print-dialog>
- 插件的使用
// 导入弹窗组件
import PrintDialog from '@/components/system/PrintDialog.vue'
//插件vue-pdf-signature
import pdf from "vue-pdf-signature";
import CMapReaderFactory from "vue-pdf-signature/src/CMapReaderFactory.js";
export default {
components: {
PrintDialog,
pdf,
},
data() {
return {
printDialog: {
title: 'pdf',
visible: false,
height: 800,
width: 1670,
},
pdfUrl: '',
}
},
methods: {
// 打印
async print(row) {
let params = {
// 组装参数
pdf: row.组装参数,
...
...
}
let res = await materialWeighApi.print(params);
this.getObjectUrl(res.data);
this.printDialog.visible = true
//也可实现下载功能
// if (res) {
// constcontent = res.data; // 文件流
// const blob = new Blob([content], {
// type: 'application/octet-stream'
// });
// // 如果后端返回文件名
// const fileName = res.fileName;
// if ('download' in document.createElement('a')) {
// // 非IE下载
// const link = document.createElement('a');
// link.download = fileName;
// link.style.display = 'none';
// link.href = URL.createObjectURL(blob);
// console.log('ee', link.href);
// document.body.appendChild(link);
// link.click();
// URL.revokeObjectURL(link.href); // 释放URL 对象
// document.body.removeChild(link);
// }
// }
},
},
getObjectUrl(data) {
let url= null;
let file = new Blob([data], {type: "application/pdf" });
if (window.createObjectURL != undefined) {
url = window.createObjectURL(file);
} else if (window.webkitURL != undefined) {
// 兼容谷歌
try {
url = window.webkitURL.createObjectURL(file);
} catch (error) {}
} else if (window.URL != undefined) {
// 兼容其他
try {
url = window.URL.createObjectURL(file);
} catch (error) {}
}
//这里是重点,将处理的url使用CMapReaderFactory方法在进行处理
url = pdf.createLoadingTask({ url: url, CMapReaderFactory });
// 将转化后url赋值
this.pdfUrl = url;
},
//dialog打印取消事件
printClose() {
this.printDialog.visible = false;
},
//dialog打印确认
printConfirm() {
this.$refs.pdf.print();
this.printDialog.visible = false
},
}