项目技术栈:若依分离版 前端vue2+ gofastdfs
需求:用户上传pdf格式文件后,供同部门人员预览
缺点:请求拿到整个数据,才能渲染, 比较耗内存.
优点:不用写服务端的代码.直接前端就可以搞定.
实现思路:直接读取写入到数据库的文件下载地址,写在iframe中,会触发自动下载,搜索其他同行的处理方式,大部分都是PDF.js,看了实现代码,还得转码,生成canvas,交给PDF.js渲染, 对于大文件来说,体验很差.我的解决方案是:axios请求BLOB,写入到iframe,自测发现时间也很长, 但点开一次后,再点第二次会秒开.优化代码添加了判定逻辑. 将结果储存到一个对象中,每次预览时,判断对象中是否有对应的结果,有的话,直接渲染,没有的话,就走请求.请求完成之前会让窗口处于loadding状态, 加载完成后,直接关闭.代码如下:
<template>
<el-dialog :title="title" :visible.sync="isPreview" width="85%" append-to-body class="resource_dialog"
:close-on-click-modal="false" v-loading="loading"
:element-loading-text="'拼命加载中,进度:' + loadingProgress + '%'"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)">
<div class="resource_cont">
<iframe :src="previewSrc" frameborder="0" width="100%" height="720px"
style="margin-bottom: -6px; background:#4a5420; border-radius: 0 0 10px 10px;"></iframe>
</div>
</el-dialog>
</template>
<script>
data(){
return {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "",
//PDF加载进度
loadingProgress: 0,
//加载过的PDF列表
loadedPDFs: {},
//预览地址
privateSrc:''
}
},
methods:{
//预览PDF函数
clientProcess(row) {
// 检查PDF是否已经在缓存中
if (this.loadedPDFs[row.uri]) {
// 如果在缓存中,直接使用缓存中的URL
this.title = "浏览PDF [" + row.name + "]";
this.previewSrc = this.loadedPDFs[row.uri];
this.loading = false;
return;
}
// row.uri 是PDF文件的URL
request.get(row.uri, {
responseType: 'blob', // 告诉axios我们期望的响应类型是blob
onDownloadProgress: progressEvent => {
// 这里处理下载进度,保留2位小数
this.loadingProgress = ((progressEvent.loaded / progressEvent.total) * 100).toFixed(2);
},
timeout: 60000,//设置超时时间
}).then((blob) => {
const isBlob = blobValidate(blob);
if (isBlob) {
const url = URL.createObjectURL(new Blob([blob], {type: 'application/pdf'}));
//保存这个url
this.loadedPDFs[row.uri] = url;
this.title = "浏览PDF [" + row.name + "]";
this.previewSrc = url;
this.loading = false;
}
}).catch((error) => {
console.error('获取PDF文件失败:', error);
});
}
},
beforeDestroy() {
// 在组件销毁前,释放所有缓存的PDF对象URL
for (let uri in this.loadedPDFs) {
URL.revokeObjectURL(this.loadedPDFs[uri]);
}
}
</script>