创建一个 "Save As" 用户脚本
Create a "Save As" userscript
这个想法在概念上很简单:
我想创建一个用户脚本,让我按下一个按钮并在页面上保存一些东西(最常见和有问题的图像)。
注意:用户脚本是 client-side(通过 Tampermonkey 和 Greasemonkey 等浏览器扩展)注入的脚本,用于向站点添加功能。
为此,我只需要调用 saveAs()
函数并将数据传递给它。
那么问题就变成了我如何获取数据。
我见过的大多数方法 运行 可能会遇到资源与脚本不在同一个域的情况?(不确定这是如何工作的)。
现在,Tampermonkey(和 Greasemonkey)已经创建了一个函数来专门处理这个问题 - GM_XMLHTTPRequest,它可以避免对适当 CORS 的需求 headers。
然而,这会为已下载的文件创建另一个对服务器的请求。
我的问题是:有没有办法不必向服务器发送二次请求?
这是我努力的记录:
根据我所做的研究,您可以创建一个 canvas
并在其中绘制图像。但是,"taints" canvas 阻止了它 运行 提取该数据的函数(例如 .toBlob()
或 .toDataURL()
)。
据我所知,CORS 提供了 2 种机制:设置正确的 HTTP headers,这需要控制服务器,以及可以放在 HTML 元素上的特殊属性:crossorigin
我尝试添加这个 属性 post-load 但它不起作用,你仍然得到一个受污染的 canvas.
Tampermonkey 提供了几种不同的选项来决定何时 运行 脚本。所以下一个想法是在加载 DOM 时 运行 ,但尚未获取资源。似乎最早可能是 document-end(更早的 getElementById
调用 returns null
)。然而,目前 returns 在页面上加载图像时出现错误(在任何其他附加代码之前 运行):
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
标志,但我不想去那里。
不,如果不向服务器发出新请求,则无法执行此操作。
当发出第一个请求时,图像被浏览器标记为不安全,然后将阻止一些功能,例如 canvas' toDataURL
、getImageData
或 toBlob
,或者在音频文件的情况下,AudioContext 的 createMediaElementSource
和 AnalyserNode
的方法以及可能的其他一些方法。
您无法规避此安全措施,一旦它被标记为不安全,它就是不安全的。
这次您必须向服务器发出新请求,以安全的方式从服务器获取新文件。
通常,您只需在发出请求之前设置媒体元素的 crossOrigin
属性,并在正确配置服务器以响应此类请求之后。
现在在你的情况下,很明显你不能配置任何将使用你的脚本的服务器。
但是正如您所注意到的,GreaseMonkey 或 TamperMonkey 等扩展程序可以从网页访问比基本 javascript 运行 更多的功能。在这些特性中,有一个允许你的浏览器对这种跨源请求不那么小心,这就是 GM_xmlhttpRequest
方法所做的。
但再一次,即使是扩展程序也没有足够的能力取消标记非安全媒体。
您必须使用安全性较低的方式执行新请求。
这个想法在概念上很简单: 我想创建一个用户脚本,让我按下一个按钮并在页面上保存一些东西(最常见和有问题的图像)。 注意:用户脚本是 client-side(通过 Tampermonkey 和 Greasemonkey 等浏览器扩展)注入的脚本,用于向站点添加功能。
为此,我只需要调用 saveAs()
函数并将数据传递给它。
那么问题就变成了我如何获取数据。
我见过的大多数方法 运行 可能会遇到资源与脚本不在同一个域的情况?(不确定这是如何工作的)。
现在,Tampermonkey(和 Greasemonkey)已经创建了一个函数来专门处理这个问题 - GM_XMLHTTPRequest,它可以避免对适当 CORS 的需求 headers。
然而,这会为已下载的文件创建另一个对服务器的请求。
我的问题是:有没有办法不必向服务器发送二次请求?
这是我努力的记录:
根据我所做的研究,您可以创建一个 canvas
并在其中绘制图像。但是,"taints" canvas 阻止了它 运行 提取该数据的函数(例如 .toBlob()
或 .toDataURL()
)。
据我所知,CORS 提供了 2 种机制:设置正确的 HTTP headers,这需要控制服务器,以及可以放在 HTML 元素上的特殊属性:crossorigin
我尝试添加这个 属性 post-load 但它不起作用,你仍然得到一个受污染的 canvas.
Tampermonkey 提供了几种不同的选项来决定何时 运行 脚本。所以下一个想法是在加载 DOM 时 运行 ,但尚未获取资源。似乎最早可能是 document-end(更早的 getElementById
调用 returns null
)。然而,目前 returns 在页面上加载图像时出现错误(在任何其他附加代码之前 运行):
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
标志,但我不想去那里。
不,如果不向服务器发出新请求,则无法执行此操作。
当发出第一个请求时,图像被浏览器标记为不安全,然后将阻止一些功能,例如 canvas' toDataURL
、getImageData
或 toBlob
,或者在音频文件的情况下,AudioContext 的 createMediaElementSource
和 AnalyserNode
的方法以及可能的其他一些方法。
您无法规避此安全措施,一旦它被标记为不安全,它就是不安全的。 这次您必须向服务器发出新请求,以安全的方式从服务器获取新文件。
通常,您只需在发出请求之前设置媒体元素的 crossOrigin
属性,并在正确配置服务器以响应此类请求之后。
现在在你的情况下,很明显你不能配置任何将使用你的脚本的服务器。
但是正如您所注意到的,GreaseMonkey 或 TamperMonkey 等扩展程序可以从网页访问比基本 javascript 运行 更多的功能。在这些特性中,有一个允许你的浏览器对这种跨源请求不那么小心,这就是 GM_xmlhttpRequest
方法所做的。
但再一次,即使是扩展程序也没有足够的能力取消标记非安全媒体。
您必须使用安全性较低的方式执行新请求。