javascript - 尝试将远程图像转换为 base64 数据的 CORS 错误

标签 javascript dom canvas cors base64

<分区>

我需要根据其 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://stackoverflow.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://stackoverflow.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://stackoverflow.com' is therefore not allowed access.

也试过:

img.crossOrigin = 'anonymous';

得到了同样的结果。

方法 3(使用 img 元素的 Canvas ):

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 header ?

有谁知道这个问题的解决方案吗?

感谢您的帮助。

最佳答案

您可以通过 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 header (如上所述)的原因。

您可以使用 https://github.com/Rob--W/cors-anywhere/ 中的代码非常轻松地设置自己的 CORS 代理,而不是像本答案中的代码片段那样使用第三方代理。等等。


As an aside, I'm not sure exactly what the CORS policy is protecting against here.

在这种特殊情况下,它根本没有真正防止任何东西,因为你可以到达 https://blog.xenproject.org/wp-content/uploads/2014/10/Testing.jpg使用任何服务器端编程语言或公共(public)代理或 curl 或其他任何东西。

https://blog.xenproject.org 的维护者正确的做法是让他们的服务器自己配置为发送一个 Access-Control-Allow-Origin 响应头,告诉浏览器允许从任何来源获取他们的内容。但由于他们没有,您只需要使用代理即可。

CORS 限制真正有用的唯一情况是在内部网上或在某种防火墙后面运行的资源。因为在内网/防火墙的情况下,让任意网络应用以与内网/防火墙内的用户相同的权限运行并不是一个好主意。

关于javascript - 尝试将远程图像转换为 base64 数据的 CORS 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43324285/

相关文章:

javascript - 在fabric.js中添加颜色减淡/分割混合模式

javascript - 如何将多个 svgs 转换为 png,因为它们在 html 上?

javascript - 固定通知重叠

javascript - window.onload 并不总是有效。为什么

javascript - 使 var 值在按钮单击中可用

javascript - 禁用 sap.ui.commons.Accordion 的重新排序

javascript - 我可以打开一个新窗口并用字符串变量填充它吗?

javascript - 同步jquery调用 - 如何等待jquery方法执行完成?

javascript - 使用 Javascript 触发创建新的 Facebook 评论框

javascript - 使用 Canvas 对路径的一部分进行动画处理