尝试将远程图像转换为 base64 数据的 CORS 错误
CORS errors trying to convert remote image to base64 data
鉴于其 URL,我需要将远程图像转换为 base64,但我 运行 遇到 CORS 错误并且不确定如何解决。
我遵循了这个问题的一些解决方案:How to convert image into base64 string using javascript
我的示例图像是:https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg
方法 1(FileReader):
function toDataUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
toDataUrl('https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg', function(data) { console.log(data)} );
这会产生错误:
XMLHttpRequest cannot load
https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://whosebug.com' is therefore not allowed
access.
方法 2 (Canvas)
function toDataUrl(src, callback, outputFormat) {
var img = new Image();
img.crossOrigin = 'use-credentials';
img.onload = function() {
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
};
img.src = src;
if (img.complete || img.complete === undefined) {
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
img.src = src;
}
}
toDataUrl('https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg', function(data) { console.log(data)} );
尝试加载图像时产生类似的错误:
Access to Image at
'https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg'
from origin 'http://whosebug.com' has been blocked by CORS
policy: No 'Access-Control-Allow-Origin' header is present on the
requested resource. Origin 'http://whosebug.com' is therefore not
allowed access.
也试过:
img.crossOrigin = 'anonymous';
得到了相同的结果。
方法 3(Canvas 使用 img 元素):
img = document.createElement('img');
img.onload = function() {
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL('image/jpg');
console.log(dataURL);
};
img.src = 'https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg';
这种方式至少加载了图像,但在调用 toDataURL 时失败:
Uncaught DOMException: Failed to execute 'toDataURL' on
'HTMLCanvasElement': Tainted canvases may not be exported.
at HTMLImageElement.img.onload (:9:22)
顺便说一句,我不确定这里的 CORS 策略到底要防止什么。假设存在某种可能触发漏洞利用的恶意负载。我们仍然在 DOM 中加载和显示图像,为什么我们会信任由同一端点设置的 CORS headers?
有谁知道这个问题的解决方案吗?
感谢您的帮助。
您可以通过 CORS proxy 发出请求来绕过 CORS 限制,如下所示:
var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
targetUrl = 'https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg'
toDataUrl(proxyUrl + targetUrl,
function(data) { console.log(data)} );
代理将请求发送到 targetUrl
,然后在收到响应后,添加 Access-Control-Allow-Origin
响应 header 和任何其他 CORS 响应 header需要它,最后将其传递回您的请求代码。
添加了 Access-Control-Allow-Origin
header 的响应是浏览器看到的内容,因此浏览器允许您的前端代码访问响应并且您不会收到任何 CORS 错误。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 解释了正在发生的事情,导致需要配置正在向其发出请求的服务器,以便它发送必要的 CORS header,或者在两者之间放置一个代理为您添加 CORS headers(如上所述)。
您可以使用 https://github.com/Rob--W/cors-anywhere/ 等代码轻松设置您自己的 CORS 代理,而不是像此答案中的代码片段那样使用 third-party 代理。
As an aside, I'm not sure exactly what the CORS policy is protecting against here.
在这种特殊情况下,它根本没有真正保护任何东西,因为您可以使用任何 server-side 编程语言或 public 代理或 curl
或其他什么。
https://blog.xenproject.org 的维护者应该将他们的服务器配置为发送 Access-Control-Allow-Origin
响应 header 告诉浏览器允许从任何来源获取他们的内容。但是因为他们没有,你只需要使用代理。
CORS 限制真正有用的唯一情况是内部网上的资源 运行 或某种防火墙后面的资源。因为在那种 intranet/firewall 情况下,让任意网络应用程序 运行 与 intranet/firewall.
中的用户具有相同的权限并不是一个好主意。
鉴于其 URL,我需要将远程图像转换为 base64,但我 运行 遇到 CORS 错误并且不确定如何解决。
我遵循了这个问题的一些解决方案:How to convert image into base64 string using javascript
我的示例图像是:https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg
方法 1(FileReader):
function toDataUrl(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var reader = new FileReader();
reader.onloadend = function() {
callback(reader.result);
}
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
}
toDataUrl('https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg', function(data) { console.log(data)} );
这会产生错误:
XMLHttpRequest cannot load https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://whosebug.com' is therefore not allowed access.
方法 2 (Canvas)
function toDataUrl(src, callback, outputFormat) {
var img = new Image();
img.crossOrigin = 'use-credentials';
img.onload = function() {
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
};
img.src = src;
if (img.complete || img.complete === undefined) {
img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
img.src = src;
}
}
toDataUrl('https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg', function(data) { console.log(data)} );
尝试加载图像时产生类似的错误:
Access to Image at 'https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg' from origin 'http://whosebug.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://whosebug.com' is therefore not allowed access.
也试过:
img.crossOrigin = 'anonymous';
得到了相同的结果。
方法 3(Canvas 使用 img 元素):
img = document.createElement('img');
img.onload = function() {
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL('image/jpg');
console.log(dataURL);
};
img.src = 'https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg';
这种方式至少加载了图像,但在调用 toDataURL 时失败:
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. at HTMLImageElement.img.onload (:9:22)
顺便说一句,我不确定这里的 CORS 策略到底要防止什么。假设存在某种可能触发漏洞利用的恶意负载。我们仍然在 DOM 中加载和显示图像,为什么我们会信任由同一端点设置的 CORS headers?
有谁知道这个问题的解决方案吗?
感谢您的帮助。
您可以通过 CORS proxy 发出请求来绕过 CORS 限制,如下所示:
var proxyUrl = 'https://cors-anywhere.herokuapp.com/',
targetUrl = 'https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg'
toDataUrl(proxyUrl + targetUrl,
function(data) { console.log(data)} );
代理将请求发送到 targetUrl
,然后在收到响应后,添加 Access-Control-Allow-Origin
响应 header 和任何其他 CORS 响应 header需要它,最后将其传递回您的请求代码。
添加了 Access-Control-Allow-Origin
header 的响应是浏览器看到的内容,因此浏览器允许您的前端代码访问响应并且您不会收到任何 CORS 错误。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 解释了正在发生的事情,导致需要配置正在向其发出请求的服务器,以便它发送必要的 CORS header,或者在两者之间放置一个代理为您添加 CORS headers(如上所述)。
您可以使用 https://github.com/Rob--W/cors-anywhere/ 等代码轻松设置您自己的 CORS 代理,而不是像此答案中的代码片段那样使用 third-party 代理。
As an aside, I'm not sure exactly what the CORS policy is protecting against here.
在这种特殊情况下,它根本没有真正保护任何东西,因为您可以使用任何 server-side 编程语言或 public 代理或 curl
或其他什么。
https://blog.xenproject.org 的维护者应该将他们的服务器配置为发送 Access-Control-Allow-Origin
响应 header 告诉浏览器允许从任何来源获取他们的内容。但是因为他们没有,你只需要使用代理。
CORS 限制真正有用的唯一情况是内部网上的资源 运行 或某种防火墙后面的资源。因为在那种 intranet/firewall 情况下,让任意网络应用程序 运行 与 intranet/firewall.
中的用户具有相同的权限并不是一个好主意。