创建一个"另存为" userscript

时间:2016-03-12 20:40:42

标签: javascript canvas cors cross-domain tampermonkey

这个想法在概念上非常简单: 我想创建一个用户脚本,让我按一个按钮并在页面上保存一些东西(最常见和有问题的图像)。 注意:用户脚本是一个注入客户端的脚本(通过浏览器扩展,如Tampermonkey和Greasemonkey),用于向站点添加功能。

为此,我只需要调用saveAs()函数并将数据传递给它。

然后问题就变成了如何获取数据。

我见过的大多数方法都遇到资源与脚本属于同一个域的情况?(不确定这是如何工作的)。

现在,Tampermonkey(和Greasemonkey)已经创建了一个函数来专门处理这个问题 - GM_XMLHTTPRequest,它可以避免使用正确的CORS头。

然而,对于已经下载的文件,这会向服务器创建另一个请求。

我的问题是:有没有办法不必向服务器发送辅助请求?

这是我努力的编年史:

通过我所做的研究,您可以创建一个canvas并在那里绘制图像。然而,这" taints"画布,阻止它运行提取该数据的函数(例如.toBlob().toDataURL()) 据我所知,CORS提供了两种机制:设置正确的HTTP标头,这需要控制服务器,以及可以放在HTML元素上的特殊属性:crossorigin
我尝试在加载后添加这个属性,它不会工作,你仍然会得到一个受污染的画布 Tampermonkey提供了几种不同的选项来运行脚本。所以接下来的想法是在加载DOM时运行,但资源还没有被提取。似乎最早可能的是文档结束(早期getElementById调用返回null)。但是,当在页面上加载图像时(在运行任何其他附加代码之前),这当前返回错误: Image from origin '...' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '...' is therefore not allowed access.
还有Chrome中的--disable-web-security标记,但我不想去那里。

1 个答案:

答案 0 :(得分:2)

不,如果没有对服务器的新请求,就无法做到这一点。

当第一个请求发出时,浏览器会将图像标记为不安全,然后会阻止一些功能,例如canvas' toDataURLgetImageDatatoBlob,或音频文件,AudioContext的createMediaElementSourceAnalyserNode方法,可能还有一些其他

没有什么可以绕过这种安全措施,一旦它被标记为不安全,它就是不安全的。 然后,您必须向服务器发出新请求,以便安全地从服务器获取新文件。

通常,您只需在执行请求之前在媒体元素上设置crossOrigin属性,并在服务器已正确配置为应答此类请求之后。

现在,在您的情况下,您似乎无法配置将使用您的脚本的任何服务器。

但是正如您所注意到的,GreaseMonkey或TamperMonkey等扩展程序可以访问比从网页运行的基本javascript更多的功能。在这些功能中,有一个允许您的浏览器不太关注此类跨源请求,这就是GM_xmlhttpRequest方法的功能。

但是,即使是分机也没有足够的力量来标记非安全媒体。

您必须使用安全性较低的方式执行新请求。