画布受到跨源数据的污染

时间:2012-12-02 22:54:20

标签: javascript canvas cross-domain cors mjpeg

我正在加载来自第三方网站的动作jpeg,我可以信任。我正在尝试getImageData(),但浏览器(Chrome 23.0)抱怨:

Unable to get image data from canvas because the canvas has been tainted by
cross-origin data.

在SO上有一些类似的问题,但他们使用的是本地文件,而我正在使用第三方媒体。我的脚本在共享服务器上运行,我没有远程服务器。

我尝试了img.crossOrigin = 'Anonymous'img.crossOrigin = ''(请参阅this post on the Chromium blog about CORS),但没有帮助。关于如何在具有跨源数据的画布上getImageData的任何想法?谢谢!

4 个答案:

答案 0 :(得分:10)

一旦受到污染,您就无法重置crossOrigin标记,但如果您事先知道图像是什么,则可以将其转换为数据网址,请参阅Drawing an image from a data URL to a canvas

但不,你不能也不应该使用不支持CORS的外部来源的getImageData()

答案 1 :(得分:9)

虽然问题很严重,但问题仍然存在,网上几乎无法解决问题。我想出了一个我想分享的解决方案:

您可以使用不首先设置crossorigin属性的图像(或视频),并测试是否可以通过AJAX通过同一资源获取HEAD请求。如果失败,则无法使用该资源。如果成功,你可以添加属性并重新设置图像/视频的来源,并附上一个重新加载它的时间戳。

此解决方法允许您向用户显示您的资源,如果不支持CORS,则只需隐藏一些功能。

HTML:

<img id="testImage" src="path/to/image.png?_t=1234">

JavaScript的:

var target = $("#testImage")[0];
    currentSrcUrl = target.src.split("_t=").join("_t=1"); // add a leading 1 to the ts
$.ajax({
    url: currentSrcUrl,
    type:'HEAD',
    withCredentials: true
})
.done(function() {
    // things worked out, we can add the CORS attribute and reset the source
    target.crossOrigin = "anonymous";
    target.src = currentSrcUrl;
    console.warn("Download enabled - CORS Headers present or not required");
    /* show make-image-out-of-canvas-functions here */
})
.fail(function() {
    console.warn("Download disabled - CORS Headers missing");
    /* ... or hide make-image-out-of-canvas-functions here */
});

在IE10 + 11和当前的Chrome 31,FF25,Safari 6(桌面版)中经过测试和使用。 在IE10和FF中,当且仅当您尝试从https脚本访问http文件时,可能会遇到问题。我还不知道解决方法。

2014年1月更新:

此处所需的CORS标头应如下所示(Apache配置语法):

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"

只有ajax请求需要x-header。据我所知,它并没有被大多数浏览器使用

答案 2 :(得分:5)

另外值得注意的是,如果您在本地工作,则无论资源是否与您正在使用的index.html文件位于同一目录中,CORS都将适用。对我来说,这意味着当我将它上传到我的服务器时,CORS问题就消失了,因为它有一个域。

答案 3 :(得分:1)

你可以在画布上使用图像的base64, 转换为base64时,您可以在图像路径之前使用代理网址(https://cors-anywhere.herokuapp.com/)以避免跨源问题

在此处查看完整详情

https://stackoverflow.com/a/44199382/5172571

var getDataUri = function (targetUrl, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        var reader = new FileReader();
        reader.onloadend = function () {
            callback(reader.result);
        };
        reader.readAsDataURL(xhr.response);
    };
    var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    xhr.open('GET', proxyUrl + targetUrl);
    xhr.responseType = 'blob';
    xhr.send();
};
getDataUri(path, function (base64) {
    // base64 availlable here
})