我需要将远程图像转换为base64给定其URL,但我遇到了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无法加载 https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg。没有 '访问控制允许来源'标题出现在请求的上 资源。起源' http://stackoverflow.com'因此是不允许的 访问。
方法2(画布)
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)} );
尝试加载图片时产生类似的错误:
访问图像 ' https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg' 来自原产地' http://stackoverflow.com'已被CORS阻止 政策:否'访问控制 - 允许 - 来源'标题出现在 请求的资源。起源' http://stackoverflow.com'因此不是 允许访问。
还试过:
img.crossOrigin = 'anonymous';
得到了相同的结果。
方法3(使用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时失败:
未捕获DOMException:无法执行' toDataURL'上 ' HTMLCanvasElement':可能无法导出受污染的画布。 在HTMLImageElement.img.onload(:9:22)
顺便说一句,我不确定CORS政策究竟在这里采取什么措施。假设存在某种可能触发漏洞利用的恶意负载。我们仍然在DOM中加载和显示图像,为什么我们会信任由同一端点设置的CORS头?
有谁知道这个问题的任何解决方案?
感谢您的帮助。
答案 0 :(得分:2)
您可以通过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
响应标头&需要任何其他CORS响应头,最后将其传递回您的请求代码。
添加了Access-Control-Allow-Origin
标头的响应是浏览器看到的,因此浏览器允许您的前端代码访问响应,并且您不会收到任何CORS错误。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS解释了发生了什么导致需要配置服务器发出请求以便发送必要的CORS头,或者在其间放置代理以为您添加CORS头(如上所述)。
而不是像在本答案的代码段中那样使用第三方代理,您可以使用https://github.com/Rob--W/cors-anywhere/之类的代码轻松设置自己的CORS代理。
顺便说一句,我不确定CORS政策究竟在这里采取什么措施。
在这种特殊情况下,它根本不能防范任何事情,因为您可以使用任何服务器端编程语言或公共代理或curl
或其他任何内容来https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg。
https://blog.xenproject.org的维护者应正确配置自己的服务器,以发送Access-Control-Allow-Origin
响应标头,告知浏览器允许从任何来源获取其内容。但由于他们没有,你只需要使用代理。
CORS限制真正有用的唯一情况是在Intranet上运行的资源或在某种防火墙后面的资源。因为在该Intranet /防火墙的情况下,使用与Intranet /防火墙内的用户相同的权限运行任意Web应用程序并不是一个好主意。