canvas.toDataURL()SecurityError

use*_*343 74 javascript canvas cors

所以我使用谷歌地图,我得到的图片,所以它看起来像这样

<img id="staticMap"
        src="http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&maptype=roadmap
&markers=color:blue%7Clabel:S%7C40.702147,-74.015794&markers=color:green%7Clabel:G%7C40.711614,-74.012318
&markers=color:red%7Ccolor:red%7Clabel:C%7C40.718217,-73.998284&sensor=false">
Run Code Online (Sandbox Code Playgroud)

我需要保存它.我发现了这个:

function getBase64FromImageUrl(URL) {
    var img = new Image();
    img.src = URL;
    img.onload = function() {

        var canvas = document.createElement("canvas");
        canvas.width = this.width;
        canvas.height = this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");

        alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));

    };
}
Run Code Online (Sandbox Code Playgroud)

但是我遇到了这个问题:

Uncaught SecurityError:无法在'HTMLCanvasElement'上执行'toDataURL':可能无法导出受污染的画布.

我搜索了修复程序.我在这里找到了一个示例如何使用CORS,但我仍然无法将这两个代码绑在一起以使其工作.也许我这样做的方式不对,有一种更简单的方法吗?我正在尝试保存此图片,以便我可以将数据传输到我的服务器.所以也许有人做了这样的事情并知道如何按需要做.toDataURL()工作?

Pri*_*ner 95

除非谷歌使用正确的Access-Control-Allow-Origin标题提供此图像,否则您将无法在画布中使用其图像.这是由于没有获得CORS批准.你可以在这里阅读更多相关内容,但它实质上意味着:

虽然您可以在画布中使用未经CORS批准的图像,但这样做会污染画布.一旦画布被污染,您就无法再将数据从画布中拉回来.例如,您不能再使用canvas toBlob(),toDataURL()或getImageData()方法; 这样做会引发安全错误.

这可以防止用户通过使用图像在未经许可的情况下从远程网站提取信息来暴露私有数据.

我建议只将URL传递给服务器端语言并使用curl下载图像.但要小心消毒!

编辑:

由于这个答案仍然是公认的答案,你应该查看@ shadyshrif的答案,即使用:

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
Run Code Online (Sandbox Code Playgroud)

只有拥有正确的权限才能使用此功能,但至少可以让您按照自己的意愿行事.

  • 我已将我的Google云存储存储桶设置为"Access-Control-Allow-Origin:*",但在尝试使用toDataURL()方法时仍然出现此安全错误.图像通过"getImageServingUrl"生成的URL提供给Canvas (4认同)
  • TIL:在设置img.src之前设置crossOrigin属性至关重要。 (2认同)

sha*_*rif 55

只需使用该crossOrigin属性并传递'anonymous'为第二个参数

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
Run Code Online (Sandbox Code Playgroud)

  • 为了澄清,这对于直接不会让资源给你的服务器不起作用.这意味着,这只适用于公共资源或配置错误的服务器. (6认同)
  • 我还必须在图像URL中添加时间戳,以避免存储服务器在没有Access-Control-Allow-Origin标头的情况下响应304.喜欢这个`img.src = url +'?' + new Date().getTime();` (3认同)

Kar*_*ban 5

此方法将防止您从您正在访问的服务器收到“访问控制允许来源”错误。

var img = new Image();
var timestamp = new Date().getTime();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url + '?' + timestamp;
Run Code Online (Sandbox Code Playgroud)