canvas.toDataURL() 安全错误

IT技术 javascript canvas cors
2021-01-11 08:04:41

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

<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">

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

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,/, ""));

    };
}

但我遇到了这个问题:

未捕获的安全错误:无法在“HTMLCanvasElement”上执行“toDataURL”:可能无法导出受污染的画布。

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

6个回答

除非谷歌使用正确的Access-Control-Allow-Origin标题提供此图像,否则您将无法在画布中使用他们的图像。这是因为没有得到CORS批准。你可以在这里阅读更多关于这个的信息,但它本质上意味着:

尽管您可以在画布中使用未经 CORS 批准的图像,但这样做会污染画布。一旦画布被污染,您就无法再从画布中取出数据。例如,您不能再使用画布 toBlob()、toDataURL() 或 getImageData() 方法;这样做会引发安全错误。

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

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

编辑:

由于这个答案仍然是公认的答案,您应该查看@shadyshrif's answer,这是使用:

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;

在您拥有正确的权限时才有效,但至少可以让您做您想做的事。

我已将我的 Google Cloud Storage 存储桶设置为“Access-Control-Allow-Origin: *”,但在尝试使用 toDataURL() 方法时仍然出现此安全错误。图像通过从“getImageServingUrl”生成的 URL 提供给 Canvas
2021-03-21 08:04:41
我会进一步采纳@Prisoner 的远程替代建议,并建议将其设为默认行为。服务器几乎肯定能够接收到img.src然后wget*/*cURL图像比客户端可以编码本地来源图像并将其发布到服务器的速度更快。也许,仅当需要客户端身份验证(即您的服务器尝试以 结束403)时,您才可以回退到使用canvas.toDataURL(img),希望它是从与页面相同的来源提供服务的。这种默认行为也将导致原始文件(EXIF 等)
2021-03-23 08:04:41
TIL:crossOrigin在设置之前设置属性至关重要img.src
2021-04-02 08:04:41
伟大的 !非常感谢这个答案!
2021-04-03 08:04:41
有什么解决办法吗?这个答案吹了。
2021-04-08 08:04:41

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

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
在 IE11 中对我不起作用,图像使用 data-url 源
2021-03-19 08:04:41
澄清一下,这不适用于直接不让资源给您的服务器。这意味着,这仅适用于公共资源或配置错误的服务器。
2021-03-20 08:04:41
我还必须向图像 URL 添加时间戳,以避免存储服务器在没有 Access-Control-Allow-Origin 标头的情况下响应 304。像这样img.src = url + '?' + new Date().getTime();
2021-04-07 08:04:41

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

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

试试下面的代码...

<img crossOrigin="anonymous"
     id="imgpicture" 
     fall-back="images/penang realty,Apartment,house,condominium,terrace house,semi d,detached,
                bungalow,high end luxury properties,landed properties,gated guarded house.png" 
     ng-src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" 
     height="220"
     width="200"
     class="watermark">
我相信这行得通的唯一原因是因为crossOrigin="anonymous"其余的都是无关紧要的。我也很确定ng-src不是原生的 javascript。
2021-03-13 08:04:41
fall-back属性值无意义的原因是什么
2021-03-18 08:04:41

就我而言,我使用的是 WebBrowser 控件(强制使用 IE 11),但无法解决错误。切换到使用 Chrome 的 CefSharp 为我解决了这个问题。