前言


使用​​vue-pdf​​插件预览数据库中以二进制存储的pdf文件


之前写的一篇是: vue-pdf查看本地pdf文件及打印乱码问题处理

后端文件以流的方式返回

@GetMapping(value="/download/{pid}")
@ApiOperation(value = "责任书下载", httpMethod = "GET", notes = "责任书下载")
public void download(
HttpServletResponse response,
HttpServletRequest request,
@ApiParam(name="pid",value="文件ID", required = true)@PathVariable(value = "pid", required = false) String pid)throws Exception {
if(StringUtils.isNotBlank(pid)){
SeAttach seAttach =seAttachManager.getByPaperId(pid);
if(null != seAttach){
String fileName = seAttach.getFileName();
byte[] data = seAttach.getFileContent();
response.setContentType("application/x-download");
if (System.getProperty("file.encoding").equals("GBK")) {
response.setHeader("Content-Disposition", "attachment;filename=\"" + new String(fileName.getBytes(), "ISO-8859-1") + "\"");
} else {
response.setHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(fileName, "utf-8") + "\"");
}
OutputStream os = null;
try {
os = response.getOutputStream();
os.write(data);
os.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (os != null) {
os.close();
}
}
}
}
}

前台处理blob流文件转化为url

handleSee(index, row) {
let that = this;
that.fileId = row.pid;// 当前行数据id
that.$store
.dispatch("hse/previewSePapers", row.pid)
.then(response => {
const xhr = new XMLHttpRequest();
const dataParams = JSON.parse(sessionStorage.currentUser); // sessionStorage中那当前用户信息
console.log("dataPram",dataParams)
xhr.open("get", response.request.responseURL);// 请求的url
xhr.setRequestHeader("Authorization", "Bearer " + dataParams.token);// 携带token访问
xhr.responseType = "blob";// blob类型
xhr.onload = function() {
if (this.status === 200) {
const blob = this.response;
const url = createObjectURL(blob);
// 将转化后 url 赋值给 vue-pdf 插件
that.src = url;
that.$refs.pdfSearch.handleOpen();
}
};
xhr.send(null);
})
.catch(e => {
that.$message.error("文件查看失败", e);
});
}

pdf插件代码

<Pdf ref="pdfSearch" :src="src" :fileId="fileId" />
<template>
<el-dialog
:visible.sync="pdfDialog"
:close-on-click-modal="false"
:show-close="false"
width="900px"
top="52px"
>
<div class="pdf" v-show="fileType == 'pdf'">
<p class="arrow">
<!-- 上一页 -->
<span
@click="changePdfPage(0)"
class="currentPage"
:class="{ grey: currentPage == 1 }"
>上一页&nbsp;&nbsp;</span
>
<span style="color: #8c8e92;">{{ currentPage }} / {{ pageCount }}</span>
<!-- 下一页 -->
<span
@click="changePdfPage(1)"
class="currentPage"
:class="{ grey: currentPage == pageCount }"
>&nbsp;&nbsp;下一页</span
>&nbsp;&nbsp;&nbsp;&nbsp;<el-button
icon="el-icon-download"
@click="download()"
type="primary"
size="mini"
>下载</el-button
>
<span
style="float :right;padding-right:40px;font-size: 20px;color: #8c8e92;cursor: pointer;"
@click="close"
><i class="el-icon-close"></i
></span>
</p>
<pdf
:src="src"
:page="currentPage"
@num-pages="pageCount = $event"
@page-loaded="currentPage = $event"
@loaded="loadPdfHandler"
></pdf>
</div>
</el-dialog>
</template>

<script>
import pdf from "vue-pdf";
export default {
name: "attachPreview",
components: { pdf },
props: ["src", "fileId"],
data() {
return {
filesProps: {
label: "originName"
},
pdfDialog: false,
currentPage: 0, // pdf文件页码
pageCount: 0, // pdf文件总页数
fileType: "pdf" // 文件类型
};
},
methods: {
// 改变PDF页码,val传过来区分上一页下一页的值,0上一页,1下一页
changePdfPage(val) {
if (val === 0 && this.currentPage > 1) {
this.currentPage--;
}
if (val === 1 && this.currentPage < this.pageCount) {
this.currentPage++;
}
},
// pdf加载时
loadPdfHandler() {
this.currentPage = 1; // 加载的时候先加载第一页
},
handleOpen() {
this.pdfDialog = true;
},
//关闭弹框
close() {
this.pdfDialog = false;
},
//附件下载
download() {
this.$store
.dispatch("hse/downloadSePapers", this.fileId)
.then(() => {
this.$message("下载成功");
})
.catch(e => {
this.$message.error("文件下载失败", e);
});
}
}
};
</script>

<style lang="stylus">
.currentPage {
cursor: pointer;
color: #8c8e92;
}

.currentPage:hover {
color: #2761ff;
}
.arrow{
position: fixed;
top: 0px;
left :0px;
z-index: 2;
width: 100%;
background-color: #191919;
padding: 12px 0;
margin: 0;
text-align :center;
}
>>>.el-dialog__body {
color: #606266;
font-size: 14px;
padding:0;
}
</style>

效果

vue-pdf预览(以二进制格式存储在数据库中的文件)_ico

数据库中对应的文件

vue-pdf预览(以二进制格式存储在数据库中的文件)_ico_02