Converting an SVG to a PDF programmatically
Searching for this topic on the web led to various libraries, all of which were no doubt very powerful, all of which were extremely large and difficult to use if one didn’t know how. Plenty of advice existed on the internet, “use library X”, but when the library has hundreds of thousands of lines that isn’t really enough information. I didn’t even mind in which programming language the solution was to be written.
After hours of searching, reading Javadocs, reading source, and experimenting, I finally came up with the following lines of Java code.
Alas, this method can only convert from a SVG file to a PDF file, i.e. these have to be files existing on the disk, they cannot be URLs, in memory, cannot be streamed, and the SVG cannot be an in-memory DOM object. My SVG is dynamic: I’m altering/creating it at runtime (after all, if I wasn’t doing that, I could just save the PDF somewhere statically in the first place and wouldn’t need to do the conversion). And I want to deliver the PDF to the browser so streaming would be good for me. But no matter, I use File.createTempFile(..)
together with file.deleteOnExit()
to create these files, and just ignore the fact that if the JVM exits abnormally, e.g. the computer suffers from a power failure, these files will never get deleted, and, over a long enough time-span, will fill up the disk until the computer fails.
Here are the lines:
import org.apache.batik.apps.rasterizer.DestinationType; import org.apache.batik.apps.rasterizer.SVGConverter; import ... // SVG is created programatically as a DOM Document Document svgXmlDoc = ... // Save this SVG into a file File svgFile = File.createTempFile("graphic-", ".svg"); svgFile.deleteOnExit(); TransformerFactory tFac = TransformerFactory.newInstance(); Transformer transformer = tFac.newTransformer(); DOMSource source2 = new DOMSource(svgXmlDoc); FileOutputStream fOut = new FileOutputStream(svgFile); try { transformer.transform(source2, new StreamResult(fOut)); } finally { fOut.close(); } // Convert the SVG into PDF File outputFile = File.createTempFile("result-", ".pdf"); outputFile.deleteOnExit(); SVGConverter converter = new SVGConverter(); converter.setDestinationType(DestinationType.PDF); converter.setSources(new String[] { svgFile.toString() }); converter.setDst(outputFile); converter.execute();
Add the following to your pom.xml
:
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-rasterizer</artifactId>
<version>1.7</version>
</dependency>
See the code in action:
https://github.com/adrianmsmith/svg-to-pdf-demo