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.createTemporaryFile together with 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");
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");
SVGConverter converter = new SVGConverter();
converter.setSources(new String[] { svgFile.toString() });

And I have the following JARs (search using Google to find the projects and download them):

  • avalon-framework-4.2.0.jar
  • batik-all-1.7.jar
  • commons-io-1.3.1.jar
  • commons-logging-1.0.4.jar
  • fop-0.95.jar
  • log4j-1.2.15.jar
  • xml-apis-ext.jar
  • xmlgraphics-commons-1.3.1.jar
  • Robin Salih

    I can’t comprehend why they work they need files. Ok, if it was some command line tool that would be fine, but if it is some library code you are calling, then they are really restricting how you use it. Also it is more work for the author of the library, they have to handle all sorts of cases of the file not existing etc.

  • Robin Salih

    Also, surely a good OS, will delete a temporary file created by a process when it exits, regardless of the circumstances. I know windows has supported the concept of temporary files since at least 3.0, although I’m not 100% convinced it automatically deletes them.

  • adrian

    Agreed, UNIX can delete temporary files as well with tmpfile, but for platform independence, Java deletes temporary files itself, when the JVM does a “normal termination” (this is part of the Java contract i.e. part of the API, it’s not an implementation detail that another JVM would be allowed implement differently.) And Java offers no facility to access the OS-specific mechanism to auto-delete temporary files.

    The correct solution, using Java, would be to have a batch job running every night deleting files from a certain directory which are over a day old.

  • Dmitry

    You can easily convert SVG to PDF using Saas service – Email them for early access.