Chrome扩展内容脚本正确加载pdf.js外部库的方法求助
如何在Chrome扩展内容脚本中正确加载pdf.js并处理在线PDF
嘿,我来帮你搞定这个问题!先拆解一下你之前遇到的两个错误,再一步步给出解决方案:
为什么之前的方法会报错?
1. Manifest中直接用CDN链接加载pdf.js失败
Chrome扩展对content_scripts里的JS文件有严格限制:必须是扩展包内的本地资源,不能直接引用外部CDN链接。这是出于安全考虑,防止恶意外部脚本注入,所以你的manifest.json会加载失败。
2. 内容脚本中调用chrome.tabs.executeScript报错
内容脚本运行在和页面隔离的沙箱环境里,没有权限使用chrome.tabsAPI——这个API只能在后台脚本(background)、弹出页(popup)或者选项页里调用,所以你在内容脚本里访问chrome.tabs会得到undefined,进而触发TypeError。
正确的解决方案步骤
第一步:下载pdf.js到扩展本地
先去pdf.js官方仓库下载编译好的核心文件:pdf.js和pdf.worker.js,把它们放到你的扩展目录里,比如新建一个libs文件夹来存放,这样路径就是./libs/pdf.js和./libs/pdf.worker.js。
第二步:调整Manifest配置
根据你用的Manifest版本(V2/V3),更新权限和基础配置:
Manifest V3 示例:
{ "manifest_version": 3, "name": "你的扩展名称", "version": "1.0", "permissions": ["activeTab", "scripting", "tabs"], "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"] } ], "background": { "service_worker": "background.js" }, "action": { "default_popup": "popup.html" } }
Manifest V2 示例:
{ "manifest_version": 2, "name": "你的扩展名称", "version": "1.0", "permissions": ["activeTab", "tabs"], "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content.js"] } ], "background": { "scripts": ["background.js"] }, "browser_action": { "default_popup": "popup.html" } }
第三步:修改弹窗脚本(popup.js)
把之前的jQuery代码换成原生JS(或者保留jQuery,但确保你引入了jQuery文件),监听复选框变化并发送消息:
document.getElementById('check_id').addEventListener('change', function() { const msg = { pdf: this.checked ? 'yes' : 'no' }; chrome.tabs.query({ currentWindow: true, active: true }, tabs => { chrome.tabs.sendMessage(tabs[0].id, msg); }); });
第四步:更新内容脚本(content.js)
内容脚本不再直接加载pdf.js,而是先判断页面是否为PDF,再请求后台脚本加载资源:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.pdf === 'yes') { // 先验证当前页面是否是PDF if (document.contentType === 'application/pdf') { // 向后台请求加载pdf.js chrome.runtime.sendMessage({ action: 'loadPdfJs' }, () => { // 资源加载完成后处理PDF handlePdf(); }); } else { console.log('当前打开的不是PDF页面哦'); } } else { // 处理普通HTML页面的逻辑 console.log('开始处理普通HTML页面'); } }); function handlePdf() { // 手动指定pdf.worker.js的路径(关键!防止worker加载失败) PDFJS.GlobalWorkerOptions.workerSrc = chrome.runtime.getURL('libs/pdf.worker.js'); // 加载当前页面的PDF PDFJS.getDocument({ url: window.location.href }).then(doc => { console.log(`这个PDF一共有${doc.numPages}页`); // 这里可以添加你的PDF处理逻辑,比如提取文本、渲染页面等 }).catch(err => { console.error('加载PDF失败:', err); }); }
第五步:后台脚本处理资源加载
Manifest V3(background.js,service worker):
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === 'loadPdfJs') { // 动态注入本地的pdf.js和pdf.worker.js chrome.scripting.executeScript({ target: { tabId: sender.tab.id }, files: ['libs/pdf.js', 'libs/pdf.worker.js'] }, () => { sendResponse(); }); return true; // 标记为异步响应 } });
Manifest V2(background.js):
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { if (message.action === 'loadPdfJs') { // 先加载pdf.js,再加载worker chrome.tabs.executeScript(sender.tab.id, { file: 'libs/pdf.js' }, () => { chrome.tabs.executeScript(sender.tab.id, { file: 'libs/pdf.worker.js' }, () => { sendResponse(); }); }); return true; // 标记为异步响应 } });
几个关键注意事项
- 确保
pdf.js和pdf.worker.js的路径和你Manifest/代码里写的一致,路径错误会导致加载失败。 - 在Chrome内置的PDF viewer中,
document.contentType会返回application/pdf,可以用这个来判断页面类型。 - 必须用
chrome.runtime.getURL()获取扩展内资源的正确路径,尤其是pdf.worker.js,否则会因为跨域问题加载失败。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

