0

I'm building a tool that generates an SVG chart. The tool is invoked via a browser (REST url). The generation is quite a time and resources consuming task and is actually stateless in a sense that it is not possible to issue the same request and get the same SVG.

I need a user to be able to save the snapshot (the SVG) via its browser. The best approach I could think of is to embed a DOWNLOAD_ME link in the image itself, that packs the displayed SVG and downloads it as a file.

However, I can't just make it work. What am I doing wrong? Is there a better/easier/more portable approach to achieve my goal here?

What's not working for me:

<svg contentScriptType="text/ecmascript" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" version="1.0" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<script type="text/ecmascript">
<![CDATA[
    function downloadAsFile() {
    var svg = document.getElementsByTagName('svg')[0];
    var serializer = new XMLSerializer();
    var source = serializer.serializeToString(svg);
    if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){
      source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
    }
    if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){
      source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
    }
    source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
    var url = "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source);
    var title = document.getElementById('title-text');
    title = title ? title.textContent : 'snapshot';
    var anchor = document.getElementById('generated-download-link');
    if (!anchor) { 
      anchor = document.createElement('a');
      anchor.id = 'generated-download-link';
      anchor.setAttribute('download', title + '.svg');
      anchor.setAttribute('href', url);
      // anchor.setAttribute('download', url);
      // anchor.setAttribute('href', '');
      svg.appendChild(anchor);
    }
    anchor.dispatchEvent(new Event('click'));
    console.log(anchor);
    // anchor.remove();
  }
  ]]>
</script>
<g id="test"> 
 <a download="myFile.svg" onclick="downloadAsFile()" href="#" ><text font-family="Verdana" font-size="16" x="10" y="20">Download me</text></a>
 </g>
</svg>

I get the Element logged just fine, it's just that don't see anything else happening apart from the logging.

And I am generating the link on-event, because the chart can be quite big in size (tens of megabytes), and I don't really want to bloat the payload size from the API.

EDIT: I forgot to add - it's an interactive SVG chart I'm building - a flamegraph. And it must remain interactive.

REFERENCES

netikras
  • 422
  • 4
  • 12

1 Answers1

0

@ControlAltDel was right. There in fact is a [Save As] item in the context menu. Silly me - since I was dealing with links I assumed that menu item saves contents of the link as a file.

Still, it would be nice to know why my javascript approach didn't work.

netikras
  • 422
  • 4
  • 12