拖拽PDF后需用FileReader.readAsArrayBuffer()读取为ArrayBuffer再传给PDF.js;必须设workerSrc且版本匹配;iframe无法直接加载本地文件,仅支持URL;canvas需设宽高属性,移动端需降级input[type="file"]。

拖拽PDF文件后怎么用 FileReader 读取并传给 PDF.js
直接用 FileReader.readAsArrayBuffer(),不能用 readAsDataURL() —— PDF.js 的 getDocument() 只接受 ArrayBuffer、Uint8Array 或 URL 字符串。用错方法会导致 Invalid PDF structure 错误或静默失败。
关键步骤:
- 在
drop事件中调用e.preventDefault(),再从e.dataTransfer.files取出 PDF 文件 - 检查
file.type === 'application/pdf',避免用户拖入 ZIP 或 DOCX 导致解析崩溃 - 用
new FileReader()调用readAsArrayBuffer(file) -
onload回调里把e.target.result(即ArrayBuffer)传给pdfjsLib.getDocument()
为什么 iframe 拖进去就白屏,但 PDF.js 能行
因为 iframe src 必须是 URL,而拖拽得到的 File 对象没有 URL;你不能直接把本地文件路径赋给 src(浏览器会拒绝 file:// 协议,且路径不可访问)。iframe 方案只适用于已有线上 PDF 地址的场景。
常见误操作:
立即学习“前端免费学习笔记(深入)”;
- 试图把
URL.createObjectURL(file)得到的 blob URL 塞进iframe—— 看似能加载,但 iOS Safari 仍强制下载,Chrome 可能报CORS或渲染不全 - 漏掉
URL.revokeObjectURL(),导致内存泄漏(尤其多文件反复拖拽) - 没配
Access-Control-Allow-Origin就对跨域 PDF 用iframe,控制台无报错但白屏
PDF.js 渲染前必须设 workerSrc,否则卡死无提示
pdfjsLib.GlobalWorkerOptions.workerSrc 不设或设错,页面不会报红字错误,只会卡在 “loading…” 或控制台静默输出 Failed to load worker。这个 worker 是解析 PDF 结构的后台线程,没它连第一页都画不出来。
正确写法(注意版本号要匹配):
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js';
或者用本地路径(推荐):
pdfjsLib.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.min.js';
注意:pdf.worker.min.js 和主库 pdf.min.js 版本必须严格一致,混用会导致 TypeError: Cannot read property 'length' of undefined。
拖拽区域里预览 PDF 的最小可行结构
不需要 jQuery,纯原生 JS + PDF.js 就够。核心是把拖拽、读取、渲染三步串起来,中间任何一步出错都要有 fallback 提示。
关键代码片段:
const dropZone = document.getElementById('drop-zone');
const canvas = document.getElementById('pdf-canvas');
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
const file = e.dataTransfer.files[0];
if (!file || file.type !== 'application/pdf') return;
const reader = new FileReader();
reader.onload = async (e) => {
const pdfData = new Uint8Array(e.target.result);
const pdfDoc = await pdfjsLib.getDocument(pdfData).promise;
const page = await pdfDoc.getPage(1);
const viewport = page.getViewport({ scale: 1.5 });
canvas.height = viewport.height;
canvas.width = viewport.width;
const ctx = canvas.getContext('2d');
await page.render({ canvasContext: ctx, viewport }).promise;
};
reader.readAsArrayBuffer(file);
});
容易被忽略的点:
-
canvas必须有明确宽高(CSS 设置无效),否则渲染空白 - 移动端 touch 事件不触发
drop,得靠input[type="file"]降级 - 大 PDF(>10MB)首次加载慢,要加 loading 状态,别让用户以为卡死了



















