问题描述
如何以编程方式将 SVG 文件转换为 PDF?(在生成 PDF 之前,我需要在某些方面更改 SVG,因此仅使用工具对其进行预转换是不够的.)
How would one go about converting a SVG file to a PDF programatically? (I need to alter the SVG in certain respects before generating the PDF so simply pre-converting it using a tool won't be sufficient.)
最好使用 Java,但 Perl 或 PHP 也可以.
Ideally using Java but Perl or PHP would be fine too.
显然,我基本上是在考虑将 Apache FOP 和 Batik 与 Java 结合使用.然而,无论我搜索多久,我都找不到关于如何做的简单介绍.诸如 SVGConverter 之类的描述具有定义能够转换部分或全部 GraphicContext 的类的接口",但我真的不知道这意味着什么.
Obviously I am basically considering Apache FOP and Batik with Java. However no matter how long I search I cannot find a simple introduction on how to do it. Things like SVGConverter have descriptions like "Defines the interface for classes that are able to convert part or all of a GraphicContext", but I don't really know what that means.
我有一种感觉,必须有一个 API 来非常简单地完成此操作,由 FOP 或 Batik 提供,但我目前无法找到它(或者它可能真的不存在.)
I have this feeling there must be an API to do this quite simply, provided by FOP or Batik, but I'm just not able to find it at the moment (or perhaps it really doesn't exist.)
就我需要的支持的 SVG 功能而言,该文件有一些路径填充了一些线性渐变.
In terms of the supported SVG features I need, the file has some paths which are filled with some linear gradients.
理想情况下,如果我可以将 SVG 作为 DOM 文档传入,那将是理想的;然后我将加载我的模板 SVG 文件,按照用户的指定进行更改,然后生成 PDF.
Ideally if I could pass the SVG in as a DOM Document that would be ideal; then I would load my template SVG file, change it as specified by the user, and then generate the PDF.
推荐答案
感谢 Adrian 展示了应该如何使用 Batik 光栅化 API.但是,我需要一个更轻量级的解决方案——我不能写入临时文件,我想要更少的依赖项.所以,从他所指的方法开始,我找到了一种访问低级代码进行转换的方法,没有别的.
Thanks to Adrian for showing how the Batik rasterizer API is supposed to be used. However, I needed a more lightweight solution--- I can't write to temporary files, and I want fewer dependencies. So, starting from the methods he pointed to, I found a way to access the lower-level code to do the conversion and nothing else.
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
重点是TranscoderInput
和 TranscoderOutput
可以与任何 InputStream
和 OutputStream
,不仅仅是文件流.请注意,其中一个构造函数采用 org.w3c.dom.Document
,这意味着您甚至不需要将 SVG DOM 序列化为 SVG 字符串,从而节省了额外的步骤.
The important point is that TranscoderInput
and TranscoderOutput
can work with any InputStream
and OutputStream
, not just file streams. Note that one of the constructors takes a org.w3c.dom.Document
, which means that you don't even need to serialize an SVG DOM into an SVG string, saving an additional step.
与高级 API 不同,此版本也不向 stdout/stderr 写入任何内容.
This version also doesn't write anything to stdout/stderr, unlike the high-level API.
对于 JPEG、PNG 或 TIFF 输出,将 org.apache.fop.svg.PDFTranscoder
替换为 org.apache.batik.transcoder.image.JPEGTranscoder
,PNGTranscoder
或 TIFFTranscoder
(注意这些光栅格式在不同的包中).
For JPEG, PNG, or TIFF output, replace org.apache.fop.svg.PDFTranscoder
with org.apache.batik.transcoder.image.JPEGTranscoder
, PNGTranscoder
, or TIFFTranscoder
(note that these raster formats are in a different package).
(我不太确定 Java 如何找到 org.apache.batk.transcoder.*
和 org.apache.fop.svg.PDFTranscoder
类,因为我在 batik-rasterizer.jar
中没有看到它们.)
(I'm not quite sure how Java finds the org.apache.batk.transcoder.*
and org.apache.fop.svg.PDFTranscoder
classes, since I don't see them in the batik-rasterizer.jar
.)
虽然简单的命令行编译仅适用于 batik-rasterizer.jar
,但它正在执行某种类加载器魔术来找到所有必要的类.在更现实的情况下(使用 Ant 构建项目),您必须手动查找类.它们可以在 Batik 项目 和 的
来自 FOP 项目.从 Batik,你需要用 batik-1.7.zip
中找到>fop-1.1.zipbatik-transcoder.jar
编译并用
Although the simple commandline-compilation works with the batik-rasterizer.jar
only, it's doing some sort of classloader magic to find all the necessary classes. In a more realistic case (building a project with Ant), you have to find the classes by hand. They can be found in batik-1.7.zip
from the Batik project and fop-1.1.zip
from the FOP project. From Batik, you need to compile with batik-transcoder.jar
and run with
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
编译并用
From FOP, you need to compile with fop.jar
and run with
fop.jar
avalon-framework-4.2.0.jar
xmlgraphics-commons-1.5.jar
这篇关于将 SVG 转换为 PDF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!