使用FileReader读取用户上传PDF乱码,求iframe设置src的正确方法
解决上传PDF文件乱码及iframe展示问题
嘿,我来帮你搞定这个问题!首先咱们先搞清楚为什么用FileReader.readAsText()读PDF会乱码——PDF是二进制格式的文件,不是纯文本,用读取文本的方法去读二进制内容,肯定会出现乱码,这完全是正常现象~你想改用iframe展示PDF的思路是对的,下面我给你一步步讲怎么实现:
核心原理:用URL.createObjectURL()生成本地临时URL
浏览器提供了URL.createObjectURL()方法,可以把用户上传的File对象转换成一个临时的本地URL,这个URL可以直接作为iframe的src属性值,让浏览器内置的PDF查看器加载并展示文件内容。
你的代码修改步骤
1. 修正文件选择的保存逻辑
你的uploadFile函数目前只是把事件对象存起来了,应该把选中的文件对象存到file变量里:
uploadFile(ev) { // 保存选中的第一个文件 this.file = ev.target.files[0]; }
2. 重写displayArticle函数
不用再用FileReader读文本了,直接生成临时URL并设置给iframe,同时保留TXT文件的文本展示逻辑:
displayArticle() { if (!this.file) { alert("请先选择文件!"); return; } // 获取iframe元素 const iframe = document.getElementById("frame"); // 先释放之前的临时URL(避免内存泄漏) if (iframe.src) { URL.revokeObjectURL(iframe.src); } // 生成当前文件的临时URL const fileUrl = URL.createObjectURL(this.file); // 设置iframe的src iframe.src = fileUrl; // 如果是TXT文件,依然用原来的方式展示文本 if (this.file.type === "text/plain") { const reader = new FileReader(); reader.onload = () => { document.getElementById("fileContents").textContent = reader.result; }; reader.readAsText(this.file); } else { // 非TXT文件(比如PDF),清空文本展示区域 document.getElementById("fileContents").textContent = ""; } }
3. 补充内存泄漏处理(可选但推荐)
因为createObjectURL会占用浏览器内存,最好在组件销毁或者用户选择新文件时释放旧的URL。比如在Vue的beforeUnmount钩子中:
beforeUnmount() { const iframe = document.getElementById("frame"); if (iframe.src) { URL.revokeObjectURL(iframe.src); } }
完整的代码示例整合
把这些修改整合到你的代码里,最终的关键部分应该是这样的:
<template> <div> <b-form-file input="file" class="mb-2 m-2" @change="uploadFile"/> <b-button class="ml-2" @click="displayArticle">Display Article</b-button> <!-- PDF展示iframe --> <iframe id="frame" src="" style="width: 100%; height: 600px; border: none;"></iframe> <!-- TXT内容展示区域 --> <pre id="fileContents" style="font-size: medium; font-weight: bold; padding: 5px;"></pre> </div> </template> <script> export default { data() { return { file: null, }; }, methods: { uploadFile(ev) { // 保存选中的第一个文件 this.file = ev.target.files[0]; }, displayArticle() { if (!this.file) { alert("请先选择文件!"); return; } const iframe = document.getElementById("frame"); // 释放旧URL if (iframe.src) { URL.revokeObjectURL(iframe.src); } const fileUrl = URL.createObjectURL(this.file); iframe.src = fileUrl; // 处理TXT文件的文本展示 if (this.file.type === "text/plain") { const reader = new FileReader(); reader.onload = () => { document.getElementById("fileContents").textContent = reader.result; }; reader.readAsText(this.file); } else { document.getElementById("fileContents").textContent = ""; } }, }, beforeUnmount() { // 组件销毁时释放URL const iframe = document.getElementById("frame"); if (iframe.src) { URL.revokeObjectURL(iframe.src); } }, }; </script>
注意事项
- 这个方法依赖浏览器的内置PDF查看器,现代主流浏览器(Chrome、Firefox、Edge等)都支持,如果你需要兼容非常老的浏览器,可能需要额外的PDF渲染库(比如PDF.js)。
- 临时URL只在当前页面会话中有效,页面刷新后就会失效,这完全符合上传文件的展示场景。
内容的提问来源于stack exchange,提问作者Esraa Saad




