【发布时间】:2011-06-22 17:06:40
【问题描述】:
我想查看当前选项卡是否是来自背景页面的 PDF 文件。
我可以在最后检查 .pdf 的网址,但有些 PDF 文件没有。
【问题讨论】:
-
您是否开发过具有此功能的扩展程序?我很想拥有这样的扩展,但不想学习如何为一些个人用途编写代码。
标签: google-chrome google-chrome-extension mime-types mime
我想查看当前选项卡是否是来自背景页面的 PDF 文件。
我可以在最后检查 .pdf 的网址,但有些 PDF 文件没有。
【问题讨论】:
标签: google-chrome google-chrome-extension mime-types mime
您可以在当前选项卡上评估属性document.contentType。
这是browserAction 的示例:
chrome.browserAction.onClicked.addListener(() => {
chrome.tabs.getSelected((tab) => {
chrome.tabs.executeScript(tab.id, { code: 'document.contentType' }, ([ mimeType ]) => {
alert(mimeType);
});
})
});
此属性返回文档呈现为的 MIME 类型,而不是 Content-Type 标头(没有关于字符集的信息)。
【讨论】:
查看页面内容是一种有点骇人听闻的方法(我不知道它是否总是有效或只是有时有效)。在那里你会找到一个用于 chrome 的 PDF 查看器的元素。它看起来是这样的:
<embed width="100%" height="100%" name="plugin" src="https://example.com/document.pdf" type="application/pdf">
您可以检查“类型”属性以查看您正在处理的内容。
【讨论】:
if (document.body.childElementCount === 1) { var embed = document.body.firstElementChild; if (embed.tagName === "EMBED" && embed.getAttribute("type") === "application/pdf") { /* do something */ } }
我不得不在我的一个扩展中做一些类似的事情,并且做了一些与@serg 给出的the answer 非常相似的事情,但使用的是 HEAD 请求。理论上,HEAD 请求应该与 GET 请求相同,但不发送响应正文,对于图像或文件,这可能需要相当多的额外数据和时间等待。
我还拆分并移动标题以删除可能附加在内容类型上的任何字符集。
getContentType: function(tab, callback){
var xhr = new XMLHttpRequest();
xhr.open("HEAD", tab.url, false);
xhr.onload = function(e) {
if (xhr.readyState === 4) {
if(xhr.status === 200) {
callback(xhr.getResponseHeader("Content-Type").split(";").shift());
}
else{
callback('Unknown');
console.error(xhr.statusText);
return;
}
}
};
xhr.onerror = function (e) {
console.error(xhr.statusText);
return;
};
xhr.send();
}
【讨论】:
仅仅为了获取 MIME 类型而发出新请求有点繁重,而且不可靠。例如,如果当前显示的页面是 POST 表单提交的结果,那么发出 GET 请求通常不会导致相同的页面。
如果您正在开发经常需要访问此信息的扩展程序,请使用chrome.webRequest API 来跟踪响应。以下演示扩展显示了单击浏览器按钮时的内容类型:
// background.js
var tabToMimeType = {};
chrome.webRequest.onHeadersReceived.addListener(function(details) {
if (details.tabId !== -1) {
var header = getHeaderFromHeaders(details.responseHeaders, 'content-type');
// If the header is set, use its value. Otherwise, use undefined.
tabToMimeType[details.tabId] = header && header.value.split(';', 1)[0];
}
}, {
urls: ['*://*/*'],
types: ['main_frame']
}, ['responseHeaders']);
chrome.browserAction.onClicked.addListener(function(tab) {
alert('Tab with URL ' + tab.url + ' has MIME-type ' + tabToMimeType[tab.id]);
});
function getHeaderFromHeaders(headers, headerName) {
for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
if (header.name.toLowerCase() === headerName) {
return header;
}
}
}
注意事项:
text/plain 时,Chrome 将回退到 MIME sniffing,除非设置了 X-Content-Type-Options: nosniff。在第一种情况下,检测到的 MIME 类型可以是任何东西。在后一种情况下,默认 MIME 类型为 text/plain。为了完整起见,这里有一个manifest.json文件,可以用来测试之前的代码:
{
"name": "Click button to see MIME",
"version": "1",
"manifest_version": 2,
"background": {
"scripts": ["background.js"],
"persistent": true
},
"browser_action": {
"default_title": "Show MIME"
},
"permissions": [
"webRequest",
"activeTab",
"*://*/*"
]
}
【讨论】:
"persistent": true,这会阻止使用现在首选的事件页面。事件页面的等效 API declarativeWebRequest 仍处于测试阶段,实际上目前似乎完全处于暂停状态。
您无法使用当前的 Chrome API afaik 获取它。您可以做的是通过XHR 再次加载此页面并检查返回的内容类型标头。像这样的:
背景 html:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if(changeInfo.status == "loading") {
if(checkIfUrlHasPdfExtension(tab.url)) {
//.pdf
pdfDetected(tab);
} else {
var xhr = new XMLHttpRequest();
xhr.open("GET", tab.url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
var contentType = xhr.getResponseHeader("Content-Type");
if(checkIfContentTypeIsPdf(contentType)) {
pdfDetected(tab);
}
}
}
xhr.send();
}
}
});
manifest.json:
"permissions": [
"tabs", "http://*/*", "https://*/*"
]
对于 PDF 文件,返回的内容类型应为 application/pdf。不过要记住的是,内容类型标头也可以包含编码:text/html; charset=UTF-8。
【讨论】:
manifest.js 中的content_scripts-文件?