将 svg 保存为 png,其中 svg 包含具有外部参考的图像

Save svg as png where svg contains images with external reference

我有一个 SVG,其中有许多引用外部图像源的图像标签(比如来自 amazon s3 存储桶)。我正在尝试将其转换为 png 像这样

canvg(document.getElementById('myCanvas'), svg);
 var imgData = document.getElementById('myCanvas').toDataURL("image/png");

我收到此错误 Uncaught SecurityError:无法在 'HTMLCanvasElement' 上执行 'toDataURL':可能无法导出受污染的画布。

我更改了我的 s3 存储桶设置 (As mentioned here)。 在canvg函数后添加了这段代码

var img = new Image();
    img.setAttribute('crossOrigin', 'anonymous');
    img.src = document.getElementById('myCanvas').value;

甚至尝试遍历所有图像标签并设置 crossOrigin 属性

我仍然遇到同样的错误。

我发现最好在服务器端进行转换,因为在 amazon s3 中允许跨源是一种安全威胁,而且许多浏览器不支持 .toDataUrl,即使提供了跨源权限也是如此。

这就是我进行转换的方式

在客户端

var s = new XMLSerializer().serializeToString(document.getElementById("svg"))
var encodedData = window.btoa(s);

然后将此编码数据传递到服务器端,在服务器端我使用 batik 库将 svg 实际转换为 png

BASE64Decoder decoder = new BASE64Decoder();
    byte[] image = decoder.decodeBuffer(encodedData);
    String fileLocation  = "C:\temp";
    String fileName = "New-" + System.currentTimeMillis();
    File file = new File(fileLocation +File.separator+ fileName + ".svg");
    FileOutputStream fop = new FileOutputStream(file);
    if (!file.exists()) {
      file.createNewFile();
    }
    fop.write(image);
    fop.flush();
    fop.close();
    PNGTranscoder transcoder = new PNGTranscoder();
    TranscoderInput tinput = new TranscoderInput(new FileInputStream(fileLocation + File.separator + fileName +".svg"));
    OutputStream ostream = new FileOutputStream(fileLocation + File.separator + fileName +".png");
    TranscoderOutput toutput = new TranscoderOutput(ostream);
    try {
          transcoder.transcode(tinput, toutput);
    } catch (TranscoderException e) { 
          System.out.println("error*");
           e.printStackTrace();
    }
    ostream.close();