PDF.js项目遇getDocument未定义及require报错问题求助
getDocument is not defined、require is not defined及MIME类型错误 我来帮你一步步拆解并解决这些问题,核心根源在于浏览器环境不支持Node.js的CommonJS require语法,同时你的HTTP服务器没有正确返回文件的MIME类型,导致ES模块加载失败,再加上脚本作用域隔离的问题,才引发了这一系列报错。
1. 修复HTTP服务器的MIME类型问题
你的当前服务器不管请求什么文件都返回text/html类型,但浏览器加载ES模块(.js文件)必须要有application/javascript的MIME类型,这就是控制台提示“non-JavaScript MIME type”的直接原因。修改你的pdfjs-start.js,添加MIME类型判断逻辑:
const http = require('http'); const url = require('url'); const fs = require('fs'); const path = require('path'); // 定义常见文件对应的MIME类型 const mimeTypes = { '.html': 'text/html', '.js': 'application/javascript', '.css': 'text/css', '.pdf': 'application/pdf', '.png': 'image/png', '.jpg': 'image/jpeg' }; http.createServer(function(req, res) { var q = url.parse(req.url, true); var filename = "." + q.pathname; // 如果请求的是目录,默认返回index.html if (filename.endsWith('/')) { filename += 'index.html'; } console.log(filename); fs.readFile(filename, function(err, data) { if (err) { res.writeHead(404, {'Content-Type': 'text/html'}); return res.end("404 Not Found"); } // 根据文件后缀匹配正确的MIME类型 const ext = path.extname(filename); const contentType = mimeTypes[ext] || 'application/octet-stream'; res.writeHead(200, {'Content-Type': contentType}); res.write(data); return res.end(); }); }).listen(9080, "");
这个修改会根据文件扩展名自动返回对应的MIME类型,彻底解决模块加载的MIME校验错误。
2. 替换require为ES模块的import语法
浏览器不支持Node.js的require语法,而你已经用了type="module"加载pdf.js的脚本,所以必须用ES模块的import来获取pdf.js导出的方法。另外,普通<script>和type="module"脚本的作用域是隔离的,普通脚本无法访问模块里的变量,因此需要把你的业务代码也改成模块脚本。
修改你的index.html脚本部分:
<!DOCTYPE html> <html> <head> <style> #canvas_container { width: 800px; height: 450px; overflow: auto; } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script> <!-- 注意:pdf.worker.js无需直接导入,pdf.js会自动加载它;若需指定路径可后续配置 --> <script type="module" src="pdf.js/src/pdf.js"></script> <script type="module" src="pdf.js/web/viewer.js"></script> <!-- 将业务代码改为模块脚本 --> <script type="module"> // 从pdf.js和viewer.js导入需要的方法与类 import { getDocument } from './pdf.js/src/pdf.js'; import { PDFViewer, PDFFindController } from './pdf.js/web/viewer.js'; var myState = { pdf: null, currentPage: 1, zoom: 1 }; let pdfFindController; // 全局保存查找控制器,方便后续调用 function loadPdfDrawing(drawingName) { getDocument(drawingName).then((pdf) => { myState.pdf = pdf; render(); // PDF加载完成后再执行文本查找,避免异步时序问题 findText('12.000'); }); var container = document.getElementById('my_pdf_viewer'); var viewer = document.getElementById('canvas_container'); var pdfViewer = new PDFViewer({ container: container, viewer: viewer }); pdfFindController = new PDFFindController({ pdfViewer: pdfViewer }); pdfViewer.setFindController(pdfFindController); } function render() { myState.pdf.getPage(myState.currentPage).then((page) => { var canvas = document.getElementById("pdf_renderer"); var ctx = canvas.getContext('2d'); // 新版pdf.js的getViewport需要传入包含scale的对象 var viewport = page.getViewport({ scale: myState.zoom }); canvas.width = viewport.width; canvas.height = viewport.height; page.render({ canvasContext: ctx, viewport: viewport }); }); } function findText(text) { if (!pdfFindController) return; pdfFindController.executeCommand('find', { caseSensitive: false, findPrevious: undefined, highlightAll: true, phraseSearch: true, query: text }); } document.addEventListener("DOMContentLoaded", function(event) { loadPdfDrawing('386-5001.pdf'); }); </script> </head> <body> <div>TODO write content</div> <div id="my_pdf_viewer"> <div id="canvas_container"> <canvas id="pdf_renderer"></canvas> </div> </div> </body> </html>
关键修改说明:
- 移除了直接导入
pdf.worker.js,新版pdf.js会自动加载worker脚本;若需自定义worker路径,可在导入后添加:import * as pdfjsLib from './pdf.js/src/pdf.js'; pdfjsLib.GlobalWorkerOptions.workerSrc = './pdf.js/src/pdf.worker.js'; - 用
import语句明确获取pdf.js和viewer.js导出的方法/类,替代无法在浏览器使用的require - 将业务代码移入
type="module"脚本,确保能访问模块导出的变量 - 调整了
getViewport的调用方式(新版pdf.js要求传入{ scale: 缩放比例 }的对象) - 优化了文本查找的调用时机,放在PDF加载完成的回调里,避免异步时序问题
3. 验证文件路径正确性
确保你的项目目录结构与脚本引用路径一致,示例结构如下:
你的项目根目录/ ├─ pdfjs-start.js ├─ index.html ├─ 386-5001.pdf └─ pdf.js/ ├─ src/ │ ├─ pdf.js │ └─ pdf.worker.js └─ web/ ├─ pdf_viewer.js └─ viewer.js
如果路径不匹配,会导致脚本加载404错误,务必确认src属性里的路径与实际文件位置对应。
总结
通过修复服务器MIME类型、改用ES模块的import语法、调整脚本作用域和异步逻辑这三个步骤,就能解决你遇到的所有错误。运行修改后的服务器,再访问http://localhost:9080/index.html,应该就能正常加载PDF并执行文本搜索了。
内容的提问来源于stack exchange,提问作者user3217883

