2

Downloading an SVG file (from the SVG file, not an HTML page)

I have a script which, when embedded in an SVG file and opened in the browser, makes changes to the SVG.

When it has finished, I would like to prompt a download of the altered file.

In a previous project, where the SVG was within an HTML page, I was able to download an SVG by adding a HTML <a> element with the SVG data as its href attribute, and then using HTMLElement.click() to trigger a Save As dialog to download the file.

In this case, however, I'm working with SVG elements in an SVG file. click() won't work on an SVG <a> element.

It works manually:

I currently have the link set up correctly so that it will download the file when manually clicked, but I can't get it to work triggering the download with javascript. This is the working (manual) code - when the circle is clicked, a Save As dialog opens with Original-Name-edited.svg as the file name, and when I click OK it correctly saves the SVG to my computer:

<svg xmlns="http://www.w3.org/2000/svg"
     viewBox="0 0 100 100">

  <a>
    <circle cx="50" cy="50" r="25" fill="red"/>
  </a>

  <script>
  // <![CDATA[
    const thisSvg = new XMLSerializer().serializeToString(document.getElementsByTagName('svg')[0])
    const link = document.getElementsByTagName('a')[0]
    const fileName = document.baseURI.replace(/(.*\/)([^\/]*)(\.svg)/, '$2-edited$3')
    const data = 'data:image/svg+xml;base64,' + btoa(thisSvg)
    link.setAttribute('download', fileName)
    link.setAttribute('href', data)
  // ]]>
  </script>

</svg>

What I have tried:

Triggering a click using dispatchEvent() rather than click() - I thought I might be able to just use onclick="return true" and it would be exactly the same as a manual click, but that didn't work. When I create a function to run on click, I can trigger an alert() or console.log(), so it feels like I'm on the right track, but I just can't get it to have the same effect as clicking on the link using the manual method.

  <a onclick="downloadSvg()">
    <circle cx="50" cy="50" r="25" fill="red"/>
  </a>
  
  <script>
  // <![CDATA[
    const thisSvg = new XMLSerializer().serializeToString(document.getElementsByTagName('svg')[0])
    const fileName = document.baseURI.replace(/(.*\/)([^\/]*)(\.svg)/, '$2-edited$3')
    const data = 'data:image/svg+xml;base64,' + btoa(thisSvg)

    const downloadSvg = () => {
      window.location.download = fileName
      window.location.href = data
      console.log(fileName)
    }

    link.dispatchEvent(new Event('click'))
  // ]]>
  </script>

</svg>

0 Answers0