- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试创建一个扩展,该扩展模仿Ctrl + Click以保存Opera 12中的图像功能。我正在使用扩展的后台脚本中的chrome.downloads.download()来启动下载,而内容脚本则在监听用户操作并发送带有图片网址的消息以进行下载。
一切正常,除了在pixiv.net之类的某些站点上,下载被中断并失败。使用webRequest API,我验证了 Activity 选项卡中的cookie是否与下载请求一起发送,但未发送引用 header 。我希望这是因为该站点阻止了来自外部站点的下载请求。不过,由于无法在失败的下载中触发webRequest.onError事件,因此我无法对此进行验证。
我无法自行设置参照 header ,因为无法通过chrome.downloads进行设置,并且webRequest.onBeforeSendHeaders不能以其阻止形式与下载请求一起使用,因此以后无法添加 header 。有没有一种方法可以在选项卡的上下文中开始下载,使其行为类似于右键单击>另存为...?
为了澄清我是如何开始下载的,这是我的TypeScript代码,其内容简化为适用的部分。
注入(inject)脚本:
window.addEventListener('click', (e) => {
if (suspended) {
return;
}
if (e.ctrlKey && (<Element>e.target).nodeName === 'IMG') {
chrome.runtime.sendMessage({
url: (<HTMLImageElement>e.target).src,
saveAs: true,
});
// Prevent the click from triggering links, etc.
e.preventDefault();
e.stopImmediatePropagation();
// This can trigger for multiple elements, so disable it
// for a moment so we don't download multiple times at once
suspended = true;
window.setTimeout(() => suspended = false, 100);
}
}, true);
interface DownloadMessage {
url: string;
saveAs: boolean;
}
chrome.runtime.onMessage.addListener((message: DownloadMessage, sender, sendResponse) => {
chrome.downloads.download({
url: message.url,
saveAs: message.saveAs,
});
});
responseType = 'blob'
的XMLHttpRequest下载图像。然后,我在Blob上使用
URL.createObjectURL()
并将该URL传递回后台脚本进行下载。这避免了数据URI的大小限制。另外,如果XHR请求失败,我将使用标准方法强制尝试,以便用户至少看到失败的下载出现。
// ...Original code here...
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
switch (message.action) {
case 'xhr-download':
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.addEventListener('load', (e) => {
chrome.runtime.sendMessage({
url: URL.createObjectURL(xhr.response),
filename: message.url.substr(message.url.lastIndexOf('/') + 1),
saveAs: message.saveAs,
});
});
xhr.addEventListener('error', (e) => {
// The XHR method failed. Force an attempt using the
// downloads API.
chrome.runtime.sendMessage({
url: message.url,
saveAs: message.saveAs,
forceDownload: true,
});
});
xhr.open('get', message.url, true);
xhr.send();
break;
}
});
interface DownloadMessage {
url: string;
saveAs: boolean;
filename?: string;
forceDownload?: boolean;
}
chrome.runtime.onMessage.addListener((message: DownloadMessage, sender, sendResponse) => {
var downloadOptions = {
url: message.url,
saveAs: message.saveAs,
};
if (message.filename) {
options.filename = message.filename;
}
var a = document.createElement('a');
a.href = message.url;
if (message.forceDownload || a.protocol === 'blob:' || !needsReferralWorkaround(a.hostname)) {
// No workaround needed or the XHR workaround is giving
// us its results.
chrome.downloads.download(downloadOptions);
if (a.protocol === 'blob:') {
// We don't need the blob URL any more. Release it.
URL.revokeObjectUrl(message.url);
}
} else {
// The XHR workaround is needed. Inform the tab.
chrome.tabs.sendMessage(sender.tab.id, {
action: 'xhr-download',
url: message.url,
saveAs: message.saveAs
});
}
});
最佳答案
chrome.download.download()
方法的第一个参数(options
)可以包含 header 属性,该属性是一个对象数组:
Extra HTTP headers to send with the request if the URL uses the HTTP[s] protocol. Each header is represented as a dictionary containing the keys name and either value or binaryValue, restricted to those allowed by XMLHttpRequest.
Referer
也不是XHR的允许头。
<a>
元素)。
chrome.downloads
API。 var suspended = false;
window.addEventListener('click', function(evt) {
if (suspended) {
return;
}
if (evt.ctrlKey && (evt.target.nodeName === 'IMG')) {
var a = document.createElement('a');
a.href = evt.target.src;
a.target = '_blank';
a.download = a.href.substring(a.href.lastIndexOf('/') + 1);
a.click();
evt.preventDefault();
evt.stopImmediatePropagation();
suspended = true;
window.setTimeout(function() {
suspended = false;
}, 100);
}
}, true);
<canvas>
元素并将图像绘制到该元素上。chrome.downloads.download()
和接收到的dataURL作为url
属性的值,接收dataURL,关闭先前打开的选项卡并启动下载。 chrome.downloads
API提供的所有便利(是否需要是不同的事情)。 toDataURL()
以96dpi的分辨率返回数据的事实。因此,尤其是对于高分辨率图像而言,这是一个秀场。toDataURLHD()
以本地 Canvas 位图分辨率返回它(数据)。toDataURLHD()
。 canvas
规范及其
toDataURL()
/
toDataURLHD()
方法
here 的更多信息。希望它将很快得到支持,并将此解决方案带回游戏中:)
manifest.json
: list content.js
:内容脚本background.js
:后台页面{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"offline_enabled": false,
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches": ["*://*/*"],
"js": ["content.js"],
"run_at": "document_idle",
"all_frames": true
}],
"permissions": [
"downloads",
"*://*/*"
],
}
var suspended = false;
window.addEventListener('click', function(evt) {
if (suspended) {
return;
}
if (evt.ctrlKey && (evt.target.nodeName === 'IMG')) {
/* Initialize the "download" process
* for the specified image's source-URL */
chrome.runtime.sendMessage({
action: 'downloadImgStart',
url: evt.target.src
});
evt.preventDefault();
evt.stopImmediatePropagation();
suspended = true;
window.setTimeout(function() {
suspended = false;
}, 100);
}
}, true);
/* This function, which will be injected into the tab with the image,
* takes care of putting the image into a canvas and converting it to a dataURL
* (which is sent back to the background-page for further processing) */
var imgToDataURL = function() {
/* Determine the image's name, type, desired quality etc */
var src = window.location.href;
var name = src.substring(src.lastIndexOf('/') + 1);
var type = /\.jpe?g([?#]|$)/i.test(name) ? 'image/jpeg' : 'image/png';
var quality = 1.0;
/* Load the image into a canvas and convert it to a dataURL */
var img = document.body.querySelector('img');
var canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL(type, quality);
/* If the specified type was not supported (falling back to the default
* 'image/png'), update the `name` accordingly */
if ((type !== 'image/png') && (dataURL.indexOf('data:image/png') === 0)) {
name += '.png';
}
/* Pass the dataURL and `name` back to the background-page */
chrome.runtime.sendMessage({
action: 'downloadImgEnd',
url: dataURL,
name: name
});
}
/* An 'Immediatelly-invoked function expression' (IIFE)
* to be injected into the web-page containing the image */
var codeStr = '(' + imgToDataURL + ')();';
/* Listen for messages from the content scripts */
chrome.runtime.onMessage.addListener(function(msg, sender) {
/* Require that the message contains a 'URL' */
if (!msg.url) {
console.log('Invalid message format: ', msg);
return;
}
switch (msg.action) {
case 'downloadImgStart':
/* Request received from the original page:
* Open the image's source-URL in an unfocused, new tab
* (to avoid "tainted canvas" errors due to CORS)
* and inject 'imgToDataURL' */
chrome.tabs.create({
url: msg.url,
active: false
}, function(tab) {
chrome.tabs.executeScript(tab.id, {
code: codeStr,
runAt: 'document_idle',
allFrames: false
});
});
break;
case 'downloadImgEnd':
/* The "dirty" work is done: We acquired the dataURL !
* Close the "background" tab and initiate the download */
chrome.tabs.remove(sender.tab.id);
chrome.downloads.download({
url: msg.url,
filename: msg.name || '',
saveAs: true
});
break;
default:
/* Repot invalie message 'action' */
console.log('Invalid action: ', msg.action, ' (', msg, ')');
break;
}
});
关于javascript - 使用chrome.downloads API发送引荐来源 header ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20579112/
我正在用 robocopy 编写一个 powershell 脚本来从列表中复制“完整的”unc/文件名路径。我遇到的问题是 robocopy 似乎在我的源路径末尾添加了一个 \。 我有一个 C:\te
我发现守护程序通过这些代码创建了一个容器 // NewBaseContainer creates a new container with its // basic configuration. fu
是否有所有潜在 map 源的列表?在示例页面上,可以浏览四种类型的 map 。外面还有什么? http://tombatossals.github.io/angular-leaflet-directi
是否有所有潜在 map 源的列表?在示例页面上,可以浏览四种类型的 map 。外面还有什么? http://tombatossals.github.io/angular-leaflet-directi
我们的网站比较多,第一次使用ElasticSearch不知道应该怎么配置ES: 我们想使用 ES 作为这些网站的唯一搜索引擎,我们是否应该为每个网站设置单独的 ES 实例? (我想这可能比一个 ES
我需要一些关于我对 UNI 项目的想法的建议。 我想知道是否可以将一个音频文件从不同的音频源分成不同的“流”。例如,将音频文件拆分为:引擎噪音、火车噪音、人声、并非始终存在的不同声音等。 我不一定需要
我想设置“公共(public)彩票”,每个人都可以看到选择是随机和公平的。如果我只需要一点,我会使用例如当天收盘道琼斯指数的 LSB。问题是,我需要 32 位。我需要一个来源: 每日可用 全世界都可以
来自 pickle 的 python 文档: Warning The pickle module is not secure. Only unpickle data you trust. 什么是 pi
我试图安排一个 liquidsoap 流媒体源在未来的特定日期和时间播放。我相信这可以使用 Liquidsoap switch 命令来完成,但我无法理解此处描述的文档:http://liquidsoa
对于Shiny应用程序,我希望能够播放在 session 本身期间生成的音频文件。 如果它是我要上传的音频文件,我将使用 tags$audio(src = "www/name.wav", ty
我想更改我的 OpenGL 来源。图片会说明: 现在是这样的: 这就是我想要的: 当前代码 gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL
我正在尝试让 Stripe 运行起来,我几乎已经完成了,但有一件令人困惑的事情。 source: 'tok_visa' 部分。看起来它可以是“tok_mastercard”、“bank_account
我已经下载了 primefaces 源代码,看看是否可以从中学习。该 jar 包含一堆使用编写器来处理渲染等的 java 类。我期待找到一些 .xhtml 文件 ... and etc etc
如果我查看页面源代码,我会看到 styling += 'ul#topnav a.tabHeader5'; styling += '{'
我正在尝试根据显示器的大小更改背景图像。它不在服务器上运行。您可以在 https://github.com/Umpalompa/Umpalompa.github.io 找到我的所有代码. 我尝试同时使
从here的最底部开始.有一个 URL 生成器,我可以使用引荐来源网址在 Google Play 上生成指向我的应用程序的链接。我如何从谷歌分析中提取该 Activity 来源?我一直在谷歌上搜索,但
我用 Google Weather API 制作了一个插件,目前我正在从 Google 的 API 中提取图像。对于晴天,我正在拉 http://www.google.com//ig/images/w
是否可以通过环境变量为 @CrossOrigin 注释指定来源?我想这样做,以便我可以将相同的代码库用于 uat/staging/production。我希望我的 uat/staging 环境可以通过
我需要等待我的 JavaScript 中的文档准备就绪,才能在正文底部插入一个 div。 我想: 使此 JavaScript 文件尽可能小(如果可能,将其编译到 < 1kb) 在闭包中内联提供文档就绪
我正在开发电子邮件服务并想连接到谷歌帐户,是否可以将我的本地主机用作授权的 JavaScript 来源? 最佳答案 第 1 步:启用 Google+ API http://localhost:4567
我是一名优秀的程序员,十分优秀!