如何使用Vue.js实现浏览器直接打开已上传的PDF文件
Vue文件上传组件新增浏览器直接打开已上传PDF功能实现
你现有组件只需要补充3部分核心逻辑即可实现需求,不需要额外依赖第三方库:
- 类型校验逻辑:判断目标文件是否为PDF格式,非PDF文件直接拦截并提示
- 临时访问地址生成逻辑:本地选择的File对象属于二进制流,无法直接被浏览器打开,需要调用
URL.createObjectURL()生成浏览器可识别的临时Blob地址;如果是已上传到服务端的PDF,直接使用服务端返回的文件访问地址即可 - 预览触发与内存回收逻辑:调用
window.open()打开地址完成预览后,调用URL.revokeObjectURL()释放临时地址,避免内存占用泄漏
补充后的完整组件代码
export default { name: "FileUpload", // 补全原有组件缺失的props声明,避免运行报错 props: { multiple: { type: Boolean, default: false }, files: { type: Array, default: () => [] }, file: { type: [File, String], default: null }, label: { type: String, required: true } }, methods: { addFile() { if (this.multiple) { let files = _.concat( this.files, Array.from(this.$refs[this.label].files) ); this.$emit("update:files", files); } else { this.$emit("update:file", this.$refs[this.label].files[0]); } // 选完文件清空input值,避免重复选同一个文件不触发change事件 this.$refs[this.label].value = '' }, removeFile(idx) { if (this.multiple) { _.pullAt(this.files, [idx]); this.$emit("update:files", this.files); } else { this.$emit("update:file", null); } }, // 新增:打开PDF方法,多文件场景传入对应文件索引 openPdf(idx = 0) { let targetFile = null // 区分单/多文件场景取目标文件 if (this.multiple) { targetFile = this.files[idx] } else { targetFile = this.file } // 边界判断:文件不存在直接返回 if (!targetFile) return // 校验文件类型:本地File对象取type,服务端返回地址判断后缀 const isPdf = (targetFile instanceof File && targetFile.type === 'application/pdf') || (typeof targetFile === 'string' && targetFile.toLowerCase().endsWith('.pdf')) if (!isPdf) { alert('仅支持打开PDF格式文件') return } let openUrl = '' // 本地未上传的File对象生成Blob地址 if (targetFile instanceof File) { openUrl = URL.createObjectURL(targetFile) // 打开后1s释放临时地址,不影响预览同时回收内存 setTimeout(() => { URL.revokeObjectURL(openUrl) }, 1000) } else { // 服务端返回的线上地址直接使用 openUrl = targetFile } // 新标签页打开PDF window.open(openUrl, '_blank') } } }
模板调用示例
你只需要在文件列表的操作项里绑定openPdf方法即可:
<template> <div class="file-upload"> <input type="file" ref="pdfUpload" accept=".pdf" @change="addFile" /> <!-- 单文件模式 --> <div v-if="!multiple && file" class="file-item"> <span>{{ file.name }}</span> <button @click="openPdf()">打开</button> <button @click="removeFile()">删除</button> </div> <!-- 多文件模式 --> <div v-for="(file, idx) in files" :key="idx" class="file-item"> <span>{{ file.name }}</span> <button @click="openPdf(idx)">打开</button> <button @click="removeFile(idx)">删除</button> </div> </div> </template>
注意:如果用户浏览器设置了PDF自动下载,需要调整浏览器的PDF预览设置为「在浏览器中打开」,该逻辑受浏览器本身配置影响,代码层面无法强制覆盖用户的浏览器设置。
内容的提问来源于stack exchange,提问作者json_stattham
相关产品推荐
相关产品推荐

