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>