将SVG转换为PDF

时间:2011-07-29 15:56:38

标签: java pdf svg

如何以编程方式将SVG文件转换为PDF? (我需要在生成PDF之前在某些方面更改SVG,因此使用工具进行预转换是不够的。)

理想情况下使用Java,但Perl或PHP也可以。

显然我基本上在考虑使用Java FOP和Batik。然而,无论我搜索多久,我都找不到如何做到的简单介绍。像SVGConverter这样的描述有​​“定义能够转换部分或全部GraphicContext的类的接口”的描述,但我真的不知道这意味着什么。

我有这种感觉必须有一个API来完成这个,非常简单,由FOP或Batik提供,但我现在无法找到它(或者它可能真的不存在。)

就我所需的支持的SVG功能而言,该文件有一些路径填充了一些线性渐变。

理想情况下,如果我可以将SVG作为理想的DOM文档传递;然后我会加载我的模板SVG文件,按照用户的指定进行更改,然后生成PDF。

5 个答案:

答案 0 :(得分:17)

感谢Adrian展示了如何使用Batik光栅化器API。但是,我需要一个更轻量级的解决方案---我无法写入临时文件,而且我需要更少的依赖项。因此,从他指出的方法开始,我找到了一种方法来访问较低级别的代码来进行转换,而不是别的。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;

import org.apache.batik.transcoder.Transcoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.fop.svg.PDFTranscoder;

public class Test {
    public static void main(String[] argv) throws TranscoderException, FileNotFoundException {
        Transcoder transcoder = new PDFTranscoder();
        TranscoderInput transcoderInput = new TranscoderInput(new FileInputStream(new File("/tmp/test.svg")));
        TranscoderOutput transcoderOutput = new TranscoderOutput(new FileOutputStream(new File("/tmp/test.pdf")));
        transcoder.transcode(transcoderInput, transcoderOutput);
    }
}

编译运行命令

javac -cp batik-rasterizer.jar -d build Test.java
java -cp build:batik-rasterizer.jar Test

重点是,TranscoderInputTranscoderOutput可以与任何InputStreamOutputStream一起使用,而不仅仅是文件流。请注意,其中一个构造函数需要org.w3c.dom.Document,这意味着您甚至不需要将SVG DOM序列化为SVG字符串,从而节省了额外的步骤。

与高级API不同,此版本也不会向stdout / stderr写入任何内容。

对于JPEG,PNG或TIFF输出,请将org.apache.fop.svg.PDFTranscoder替换为org.apache.batik.transcoder.image.JPEGTranscoderPNGTranscoderTIFFTranscoder(请注意,这些栅格格式位于不同的包中)。

(我不太确定Java如何找到org.apache.batk.transcoder.*org.apache.fop.svg.PDFTranscoder类,因为我在batik-rasterizer.jar中看不到它们。)

修改

虽然简单的命令行编译仅适用于batik-rasterizer.jar,但它正在做某种类加载器魔法来查找所有必需的类。在更现实的情况下(使用Ant构建项目),您必须手动查找类。可以在the Batik projectbatik-1.7.zipthe FOP projectfop-1.1.zip找到它们。从Batik开始,您需要使用batik-transcoder.jar进行编译并使用

运行
  • batik-transcoder.jar
  • batik-anim.jar
  • batik-awt-util.jar
  • batik-bridge.jar
  • batik-css.jar
  • batik-dom.jar
  • batik-ext.jar
  • batik-gvt.jar
  • batik-parser.jar
  • batik-script.jar
  • batik-svg-dom.jar
  • batik-util.jar
  • batik-xml.jar
  • xml-apis-ext.jar

从FOP,您需要使用fop.jar进行编译并使用

运行
  • fop.jar
  • avalon-framework-4.2.0.jar
  • xmlgraphics-commons-1.5.jar

答案 1 :(得分:5)

我终于设法找到适当的代码行来使用Batik来解决这个问题。

您需要将SVG文件和生成的PDF作为磁盘上的文件,即我找不到在内存中执行此操作的方法(我正在编写HTTP Servlet,因此我没有内在的需要编写任何内容作为一个文件,理想情况下我会将结果传输到HTTP客户端)。我使用File.createTemporaryFile创建了一个文件,将我的SVG转储到一个文件中,并将生成的PDF写入。

所以我使用的行如下:

import org.apache.batik.apps.rasterizer.DestinationType;
import org.apache.batik.apps.rasterizer.SVGConverter;
import ...

// SVG available as a DOM object (created programatically by my program)
Document svgXmlDoc = ...

// Save this SVG into a file (required by SVG -> PDF transformation process)
File svgFile = File.createTempFile("graphic-", ".svg");
Transformer transformer = TransformerFactory.newInstance().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.setDestinationType(DestinationType.PDF);
converter.setSources(new String[] { svgFile.toString() });
converter.setDst(outputFile);
converter.execute();

我有以下JAR(使用Google搜索以查找项目并下载它们):

  • 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的API-ext.jar
  • xmlgraphics-公地1.3.1.jar

答案 2 :(得分:4)

你需要一个libray来渲染svg和pdf。 我建议前者SVG salamander,后者iText。使用svg salamander,您可以读取svg并创建一个图像对象,使用itext可以将该图像写入pdf。

答案 3 :(得分:1)

我使用的是Altsoft Xml2PDF。如果我正确理解了您的所有需求和要求,您最好尝试他们的服务器版Xml2PDF。

答案 4 :(得分:1)

你需要的只是幻影。你根本不需要笨重的蜡染布;只需要运行phantomjs,调用rasterize.js,使用pdf的url作为源,并将位置作为输出。根据您对.pdf的要求,您甚至不需要Java。

http://phantomjs.org/screen-capture.html

查看以&#34开头的部分;除了PNG格式外,PhantomJS还支持JPEG,GIF和PDF。"