首先
1.安装插件:yarn add pdfh5 或者 npm install --save pdfh5
1.先做俩按钮
<el-table-column
label="反馈单"
align="center"
:width="width"
>
<template slot-scope="scope">
<el-tooltip class="item" :enterable="false" effect="dark" content="查看" placement="top" v-if="scope.row.fjPath">
<span style="color:#909399"><a class="el-icon-view" style="font-size:17px;" @click="findFeedback(scope.row)" /></span>
</el-tooltip>
<el-tooltip class="item" :enterable="false" effect="dark" content="下载" placement="top" v-if="scope.row.fjPath">
<span style="color:#ff6d6d"><a class="el-icon-download" style="font-size:17px;" @click="findFeedbackDown(scope.row.id)" /></span>
</el-tooltip>
</template>
</el-table-column>
2.业务模块调用方法
/*
* 查看反馈单
* */
async findFeedback(row) {
try {
this.pdfUrl = await pdfView({ id: row.id })
this.$router.push({ name: 'pdfView', params: { pdfUrl: this.pdfUrl }})
} catch (error) {
console.error('下载PDF失败:', error)
}
},
/*
* 下载反馈单
* */
findFeedbackDown(id) {
pdfDownLoad(id)
},
js 方法
// pdf预览
export function pdfView(data) {
return axios({
url: baseUrl + '/pdfView',
method: 'get',
params: data,
responseType: 'arraybuffer'
}).then(res => {
const blob = new Blob([res], { type: 'application/pdf' })
return URL.createObjectURL(blob)
}).catch(error => {
console.error('获取 PDF 文件时出错:', error)
})
}
// pdf下载
export function pdfDownLoad(id) {
return axios({
url: baseUrl + '/pdf/' + id,
method: 'get',
responseType: 'blob'
}).then(res => {
debugger
if (res instanceof Blob) {
const link = document.createElement('a')
link.download = id
link.href = window.URL.createObjectURL(res)
link.click()
} else {
this.$message.error('处理失败')
}
}).catch(error => {
console.error('获取 PDF 文件时出错:', error)
})
}
3.我单独做了一个预览pdf的组件,这个看具体需求
<template>
<div>
<van-nav-bar
title="反馈单查看"
left-text="返回"
left-arrow
:fixed="true"
:safe-area-inset-top="true"
:placeholder="true"
@click-left="$router.back()"
/>
<div class="m-pdf">
<div id="pdf" />
</div>
</div>
</template>
<script>
import Pdfh5 from 'pdfh5'
import 'pdfh5/css/pdfh5.css'
export default {
data() {
return {
pdfUrl: '',
pdfh5: null
}
},
mounted() {
// pdfh5实例化时传两个参数:selector选择器,options配置项参数,会返回一个pdfh5实例对象,可以用来操作pdf,监听相关事件
// pdfh5 = new Pdfh5(selector, options) goto初始到第几页,logo设置每一页pdf上的水印
this.pdfh5 = new Pdfh5('#pdf', { pdfurl: this.pdfUrl, goto: 1, x: 420, y: 700, width: 120, height: 120 })
// this.pdfh5 = new Pdfh5('#pdf', { pdfurl: this.pdfUrl, goto: 1, logo: {src: require('../../assets/image/logo.png'), x: 420, y: 700, width: 120, height: 120} })
// 监听pdf准备开始渲染,此时可以拿到pdf总页数
this.pdfh5.on('ready', function () {
console.log('总页数:' + this.totalNum)
})
// 监听pdf加载完成事件,加载失败、渲染成功都会触发
this.pdfh5.on('complete', (status, msg, time) => {
console.log('状态:' + status + ',信息:' + msg + ',耗时:' + time + '毫秒')
})
},
created() {
this.init()
},
methods: {
init() {
this.pdfUrl = this.$route.params.pdfUrl
}
}
}
</script>
<style lang="scss" scoped>
.m-pdf { // 保证pdf区域铺满整个屏幕
// 方法1:使用vw和vh视窗单位,1vw=视窗宽度的1%;1vh=视窗高度的1%
width: 100vw;
height: 100vh;
// 方法2:使用fixed定位
// position: fixed;
// top: 0;
// bottom: 0;
// right: 0;
// left: 0;
}
</style>
4.做好路由跳转
{// 公众号查看反馈单pdf
name: 'pdfView',
path: '/App-view/jkCheckUp/pdfView',
component: () => import('@/views/App-view/jkCheckUp/pdfView'),
hidden: true
},
5.Java方法
@GetMapping(value = "/pdfView")
public ResponseEntity<FileSystemResource> getPdf(@ModelAttribute QcJkInfoVo vo, HttpServletResponse response) throws IOException {
if(StringUtil.isNull(vo.getId())){
throw new MyException(502, "未找到相关体检信息!");
}
//根据id查数据库里的附件路径
QcJkInfo jkInfo = qcJkInfoService.getById(vo.getId());
if(StringUtil.isNull(jkInfo.getFjPath())){
throw new MyException(502, "未找到身份证号码为"+jkInfo.getIdCard()+"的反馈单信息!");
}
// PbhConfig.getProfile()是配置好的统一附件地址实际上就是D:/pbh/uploadPath
// pdf地址
try{
String filePath = PbhConfig.getProfile()+"/"+jkInfo.getFjPath();
File file = new File(filePath);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData(vo.getId(), vo.getId());
return new ResponseEntity<>(new FileSystemResource(file), headers, HttpStatus.OK);
}catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
@GetMapping("/pdf/{id}")
@ResponseBody
public ResponseEntity<byte[]> getPdf(@PathVariable String id) {
QcJkInfo jkInfo = qcJkInfoService.getById(id);
// pdf地址
String filePath = PbhConfig.getProfile()+"/"+jkInfo.getFjPath();
try {
byte[] pdfContent = Files.readAllBytes(Paths.get(filePath));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData(id+"pdf",id+"pdf");
return new ResponseEntity<>(pdfContent, headers, HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
6.最后实现效果
预览效果
注:我在做的时候遇到最坑的就是这个预览,其他方法包括iframe和网上的其他一些组件都可以在电脑端正常加载,但是手机端就有问题,所以我采用了这个预览方法
后期又提出一个要求,需要打印功能
这里我又加了一个打印按钮
<el-tooltip v-if="scope.row.fjPath && isMobile" class="item" :enterable="false" effect="dark" content="打印" placement="top">
<span style="color:#909399" @click="previewFile(scope.row.id)">打印</span>
</el-tooltip>
js:
/*
* 打印反馈单
* */
async previewFile(id) {
try {
const response = await axios.get(this.baseUrl + '/api/archives/jkInfo/pdfPrint/' + id, {
responseType: 'arraybuffer'
})
const blob = new Blob([response.data], { type: response.headers['content-type'] })
const url = window.URL.createObjectURL(blob)
window.open(url, '_blank')
} catch (error) {
console.error('Error previewing file:', error)
}
},
java : 方法区别在于需要设置 headers.setContentDispositionFormData(“inline”,id+“.pdf”);,其中inline是为了设置浏览器之打开不下载,否则会跟下载方法一个样
@GetMapping("/pdfPrint/{id}")
@ResponseBody
public ResponseEntity<byte[]> pdfPrint(@PathVariable String id) {
QcJkInfoVo vo = new QcJkInfoVo();
vo.setId(id);
QcJkInfoVo jkInfo = qcJkInfoService.getQcJkInfoVo(vo);
// pdf地址
String filePath = PbhConfig.getProfile()+"/jkPdf/"+jkInfo.getFjPath();
try {
byte[] pdfContent = Files.readAllBytes(Paths.get(filePath));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_PDF);
headers.setContentDispositionFormData("inline",id+".pdf");
return new ResponseEntity<>(pdfContent, headers, HttpStatus.OK);
} catch (IOException e) {
e.printStackTrace();
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}