Search code examples
jquerycross-domaincanvg

Save svg as png where svg contains images with external reference


I have an SVG with many image tags referring to external image sources(Say from amazon s3 bucket) . I am trying to convert it into png like this

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

I am getting this error Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

I have changed my s3 bucket settings (As mentioned here). Added this piece of code after canvg function

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

Even tried iterating over all the image tags and set crossOrigin attribute

Still I am getting the same error.


Solution

  • I found it better to do the conversion in server side since allowing cross origin in amazon s3 is a security threat and many browsers won't support .toDataUrl even if cross-origin permissions are given.

    This is how I am doing the conversion

    In client side

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

    And this encoded data is passed to the server side where I do the actual conversion svg to png using batik library

    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();