Igo*_*nko 5 javascript google-chrome google-chrome-extension pdf.js
我正在尝试编写用于显示PDF文件的Google Chrome扩展程序.一旦我检测到浏览器重定向到指向PDF文件的URL,我希望它停止加载默认的PDF查看器,但是开始显示我的UI.UI将使用PDF.JS呈现PDF和jQuery-ui以显示其他一些内容.
问题:我该怎么做?阻止原始PDF查看器非常重要,因为我不想通过显示文档的两个实例来消耗内存消耗.因此,我应该以某种方式将选项卡导航到我自己的视图.
Rob*_*b W 12
作为PDF.js Chrome扩展程序的主要作者,我可以分享有关为Chrome构建PDF Viewer扩展程序背后的逻辑的一些见解.
在完美的世界中,每个网站都将提供标准application/pdfMIME类型的PDF文件.不幸的是,现实世界并不完美,实际上有许多网站使用了不正确的MIME类型.您将通过选择满足以下任何条件的请求来捕获大多数情况:
Content-Type: application/pdf响应头一起提供.Content-Type: application/octet-stream响应头一起提供,其URL包含".pdf"(不区分大小写).除此之外,您还必须检测用户是否要查看 PDF文件或下载 PDF文件.如果你不关心这种区别,那很容易:如果它符合以前的任何条件,只需拦截请求.
否则(这是我采用的方法),您需要检查Content-Disposition响应头是否存在,其值是否以" attachment" 开头.
如果您想支持PDF下载(例如,通过您的UI),则需要添加Content-Disposition: attachment响应标头.如果标题已存在,则必须inline用"附件" 替换现有的处置类型(例如).不要试图解析完整的标题值,只需将第一部分剥离到第一个分号,然后将"附件"放在它前面.(如果您真的想解析标题,请阅读RFC 2616(第19.5.1节)和RFC 6266).
所述chrome.webRequestAPI可用于拦截并重定向请求.使用以下逻辑,您可以拦截PDF并将其重定向到从给定URL请求PDF文件的自定义查看器.
chrome.webRequest.onHeadersReceived.addListener(function(details) {
if (/* TODO: Detect if it is not a PDF file*/)
return; // Nope, not a PDF file. Ignore this request.
var viewerUrl = chrome.extension.getURL('viewer.html') +
'?file=' + encodeURIComponent(details.url);
return { redirectUrl: viewerUrl };
}, {
urls: ["<all_urls>"],
types: ["main_frame", "sub_frame"]
}, ["responseHeaders", "blocking"]);
Run Code Online (Sandbox Code Playgroud)
(请参阅https://github.com/mozilla/pdf.js/blob/master/extensions/chromium/pdfHandler.js,了解使用本答案顶部描述的逻辑实际执行PDF检测)
使用上面的代码,您可以截取http和https URL上的任何PDF文件.如果要查看本地文件系统和/或ftp中的PDF文件,则需要使用该chrome.webRequest.onBeforeRequest事件而不是onHeadersReceived.幸运的是,您可以假设如果文件以".pdf"结尾,则该资源很可能是PDF文件.想要使用扩展程序查看本地PDF文件的用户必须在扩展程序设置页面明确允许此操作.
在Chrome操作系统上,使用chrome.fileBrowserHandlerAPI将您的扩展程序注册为PDF查看器(https://github.com/mozilla/pdf.js/blob/master/extensions/chromium/pdfHandler-vcros.js).
基于webRequest API的方法仅适用于顶级文档和框架中的PDF,而不适用于通过<object>和嵌入的PDF <embed>.虽然它们很少见,但我仍然想支持它们,所以我提出了一种非传统的方法来检测和加载这些上下文中的PDF查看器.可以在https://github.com/mozilla/pdf.js/pull/4549/files查看实施情况.此方法依赖于以下事实:当元素放入文档时,最终必须呈现它.渲染时,将应用CSS样式.当我为CSS中的embed/object元素声明动画时,将触发动画事件.这些事件在文档中冒出来.然后,我可以为此事件添加一个侦听器,并使用加载我的PDF查看器的iframe替换object/embed元素的内容.
有几种方法可以替换元素或内容,但我使用Shadow DOM来更改显示的内容,而不会影响页面中的DOM.
这里描述的方法有一些限制:
从服务器请求至少两次PDF文件:首先是获取标题的常规请求,当扩展名重定向到PDF查看器时会中止.然后另一个请求实际数据的请求.
因此,如果文件只有一次有效,则无法显示PDF(第一个请求使URL无效,第二个请求失败).
此方法仅适用于GET请求.没有公共API可以直接从Chrome扩展程序中的请求中获取响应正文(crbug.com/104058).
获取PDF <object>以及<embed>元素工作的方法需要在每个页面上运行脚本.我已经对代码进行了分析,发现对性能的影响可以忽略不计,但是如果要更改逻辑,还是需要小心.
(我首先尝试使用Mutation Observers进行检测,这会使大型文档的页面加载速度降低3-20%,并在复杂的DOM基准测试中导致额外的1.5 GB内存使用峰值).
检测<object>/ <embed>标记的方法可能仍然会导致加载任何基于NPAPI/PPAPI的PDF插件,因为它只在已经插入和渲染时替换了<embed>/ <object>tag的内容.当选项卡处于非活动状态时,不会调度动画,因此动画事件的分派将显着延迟.
PDF.js是开源的,您可以在https://github.com/mozilla/pdf.js/tree/master/extensions/chromium上查看Chrome扩展程序的代码.如果您浏览源代码,您会发现代码比我在此处解释的要复杂一些.这是因为扩展无法在onHeadersReceived事件中重定向请求,直到几个月前我实现它(crbug.com/280464,Chrome 35).
还有一些逻辑可以使多功能框中的URL看起来更好一些.
PDF.js扩展程序继续发展,因此除非您想要显着更改PDF查看器的UI,否则我建议用户在Chrome网上应用店中安装PDF.js的官方PDF查看器,和/或打开PDF上的问题.js的问题跟踪器,用于合理的功能请求.
| 归档时间: |
|
| 查看次数: |
2592 次 |
| 最近记录: |