关于chrome安全问题的Canvas to DataURI()

Canvas toDataURI() on chrome security issue

本文关键字:to DataURI Canvas chrome 安全 问题 关于      更新时间:2023-09-26

我在chrome上的Canvas遇到问题。我知道这被提到了很多,但我没能找到一个适合我的解决方案。

基本上,我正在设计一个执行以下步骤的网站:
-将SVG图像模板从宿主服务器加载到对象中
-操作SVG(着色、隐藏和显示图层等)
-然后将操作后的版本发送到服务器,插入pdf文档并通过电子邮件发送

我的问题是最后一步。我使用的方法包括:
-获取SVG的内容文档并序列化其XML

 var s = new XMLSerializer();
 svg = document.getElementById('theSVG').contentDocument;
 var xmlTest = s.serializeToString(svg);
  • 用onLoad函数定义一个新图像,并将src应用于它:

    drawnImage.src="data:image/svg+xml,"+转义(xmlTest);

  • 创建一个画布元素并将该图像绘制到其中:

    var canvas=document.createElement('canvas');var cont=canvas.getContext('2d');cont.drawImage(drawnImage,0,0,画布宽度,画布高度);

  • 最后一步是从canvas元素中提取dataURI,如下所示:

var ImageDataURl=画布.toDataURLL();

之后,数据(base64)被发送到服务器,转换为位图并保存为服务器磁盘上的jpeg图像,然后作为大pdf文档的一部分插入。

一切都很顺利,直到我在chrome上测试了它,我发现了一个安全错误:

未捕获的SecurityError:试图突破用户代理的安全策略

当我读到这个错误时,我知道这是一个跨域镜像的chrome安全问题等等。我想知道的是:
-在用户浏览器上创建一个新画布并将图像加载到其中是否被视为来自另一个域的文件
-即使是在服务器端(我使用的是C#),我也不介意。我尝试上传SVG XML,并尝试将其转换为base64字符串,但没有成功

如有任何帮助,我们将不胜感激。

在Chrome上,将SVG图像加载到画布会污染画布,这意味着尽管你仍然可以对其进行写入,但你无法从中读取任何数据。如果你避免使用某些SVG元素(如<foreignObject>),Chrome最近似乎已经修复了这一问题,所以它可能很快就会出现在Chrome发布版本中。

同时,也许你可以使用Firefox,这样不会污染画布。

我使用fabric js解决了这个问题。伟大的图书馆。代码如下:

var a = document.getElementById("theSVG"); //This is the <object>
a.setAttribute('data', 'worldmap.svg'); //Setting the data attribute to the svg file

a.onload = function () {
    var svgDoc = a.contentDocument;
    var s = new XMLSerializer();
    var xml = s.serializeToString(svgDoc);

    var canvas = new fabric.Canvas('canvas');
    var svg = xml;
    fabric.loadSVGFromString(svg, function (objects, options) {
        var loadedObject = fabric.util.groupSVGElements(objects, options);
        canvas.add(loadedObject);
        canvas.calcOffset();
        canvas.renderAll();
        if (!fabric.Canvas.supports('toDataURL')) {
            alert('This browser doesn''t provide means to serialize canvas to an image');
        }
        else {
            window.open(canvas.toDataURL('png'));
        }
    });
}

这解决了.toDataURL()问题。但是我的SVG文件有问题。希望这能有所帮助。

嗨,我正在做下面的事情。我没有犯任何错误。希望这对你有所帮助。

<script type="text/javascript">
$("#exportButton").click(function() { 
    html2canvas( [ document.getElementById("divId_for_Pdf") ], {
       onrendered: function(canvas) {
           var dataUrl = canvas.toDataURL();
         // $('#img1').attr('src',dataUrl);
           var action ='saveChartData';
            var data="dataUrl="+dataUrl;
           $.ajax({url:action, data:data, dataType:'text',type:'POST',cache:false,
               success: function(data) {
                 //alert("success..........!")
                   window.location.href = "${grailsApplication.config.grails.serverURL}/adminConfig/downloadAnalyticsChart?tenantName=${tenantInstance?.tenantName}&from=Dashboard"
               },
               error: function(request, status, error) {
                   alert('error');
               },
               complete: function(data){
               }
           });
       }
   });
});        
</script>

问题的一个原因是当您为图像使用另一个"域"时。。。

如果您尝试从域的Url中获取DataUrl,它会起作用,否则不会。

我找到了这个答案

然后我添加了

access-control-allow-origin: *
access-control-allow-credentials: true

在我的服务器上,但没有工作。。。

最后我试了一下。我只是放了一个img.crossOrigin="Anonymous";和标题

这确实奏效了。