当前位置: 首页 > 知识库问答 >
问题:

使用Java和Apache Batik从SVG生成多页PDF

茹康裕
2023-03-14

我有两个简单的SVG文档,我想将它们转换为PDF,这样每个文档都位于PDF中的一个页面上。

我的第一个SVG文档有两个矩形,如下所示:

第二个是一个黑色的圆圈。

代码如下:

import java.io.*;
import org.apache.batik.anim.dom.*;
import org.apache.batik.transcoder.*;
import org.w3c.dom.*;

public class MultiPagePdf {

  public static void main(String[] args) {

    MultiPagePDFTranscoder transcoder = new MultiPagePDFTranscoder();
    try {
      final DOMImplementation impl = SVGDOMImplementation.getDOMImplementation();
      SVGOMDocument doc1 = (SVGOMDocument) impl.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);

      // 1st rectangle in doc1
      Element el = doc1.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "rect");
      el.setAttributeNS(null, "width", "60");
      el.setAttributeNS(null, "height", "60");
      el.setAttributeNS(null, "fill", "none");
      el.setAttributeNS(null, "stroke", "blue");
      SVGOMSVGElement docEl = (SVGOMSVGElement) doc1.getDocumentElement();
      docEl.appendChild(el);

      // 2nd rectangle in doc1
      Element ell = doc1.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "rect");
      ell.setAttributeNS(null, "x", "50");
      ell.setAttributeNS(null, "y", "50");
      ell.setAttributeNS(null, "width", "25");
      ell.setAttributeNS(null, "height", "25");
      ell.setAttributeNS(null, "fill", "green");
      docEl.appendChild(ell);

      final DOMImplementation impl2 = SVGDOMImplementation.getDOMImplementation();
      SVGOMDocument doc2 = (SVGOMDocument) impl2.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
      // circle in doc2
      Element el2 = doc2.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "circle");
      el2.setAttributeNS(null, "cx", "130");
      el2.setAttributeNS(null, "cy", "100");
      el2.setAttributeNS(null, "r", "50");
      SVGOMSVGElement docEl2 = (SVGOMSVGElement) doc2.getDocumentElement();
      docEl2.appendChild(el2);

      OutputStream outputStream = new FileOutputStream(new File("/C:/Users/ah/Documents/simpleMulti.pdf"));
      TranscoderOutput transcoderOutput = new TranscoderOutput(outputStream);

      Document[] doccs = { doc1, doc2 };
      transcoder.transcode(doccs, null, transcoderOutput); // generate PDF doc
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

我已经打印了两个SVG文档,它们看起来应该是:

第一份SVG文件:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="text/ecmascript" zoomAndPan="magnify" contentStyleType="text/css" preserveAspectRatio="xMidYMid meet" version="1.0">
    <rect fill="none" width="60" height="60" stroke="blue"/>
    <rect fill="green" x="50" width="25" height="25" y="50"/>
</svg>

第二份SVG文件:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" contentScriptType="text/ecmascript" zoomAndPan="magnify" contentStyleType="text/css" preserveAspectRatio="xMidYMid meet" version="1.0">
    <circle r="50" cx="130" cy="100"/>
</svg>

我发现了一个代码,在使用ApacheFop之后,它应该做我正在做的事情;我有以下代码来生成PDF:

import java.io.*;
import java.util.*;
import org.apache.batik.transcoder.*;
import org.apache.fop.*;
import org.apache.fop.svg.*;
import org.w3c.dom.*;

public class MultiPagePDFTranscoder extends AbstractFOPTranscoder {

  protected PDFDocumentGraphics2D graphics = null;
  protected Map<String, Object> params = null;

  public MultiPagePDFTranscoder() {
    super();
  }

  protected void transcode(Document[] documents, String uri, TranscoderOutput output) throws TranscoderException {
    graphics = new PDFDocumentGraphics2D(isTextStroked());
    graphics.getPDFDocument().getInfo().setProducer("Apache FOP Version " + Version.getVersion() + ": PDF Transcoder for Batik");

    try {
      OutputStream out = output.getOutputStream();
      if (!(out instanceof BufferedOutputStream)) {
        out = new BufferedOutputStream(out);
      }
      for (int i = 0; i < documents.length; i++) {
        Document document = documents[i];
        super.transcode(document, uri, null);
        int tmpWidth = 300;
        int tmpHeight = 300;
        if (i == 0) {
          graphics.setupDocument(out, tmpWidth, tmpHeight);
        } else {
          graphics.nextPage(tmpWidth, tmpHeight);
        }

        graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
        graphics.transform(curTxf);
        this.root.paint(graphics);
      }
      graphics.finish();
    } catch (IOException ex) {
      throw new TranscoderException(ex);
    }
  }
}

生成PDF文件,但我有两个问题。

>

  • SVG元素的平移和缩放不正确。

    在第二页上,存在第一个文档(我尝试了多个页面,所有以前的文档都存在于当前页面上)。

    我使用ApacheFop2.1和ApacheBatik1.8。

    任何一个问题的帮助将高度赞赏。我也愿意为我的整体任务提供其他解决方案(将SVG转换为多页PDF)。

  • 共有2个答案

    于正志
    2023-03-14

    RSVG-转换可以将多个svg-文档转换成单个PDF。

    rsvg-convert -f pdf -o out.pdf file1.svg file2.svg file3.svg
    

    或对于文件夹中的所有文件:

      rsvg-convert -f pdf -o out.pdf *.svg
    

    但我不知道如何使用Java实现这一点。只是一个想法。。。

    姬俊驰
    2023-03-14

    我也有类似的问题。我去的方式是使用Batik中的SVGConzer应用程序(org.apache.batik.apps.rasterizer.SVGConzer)将单个SVG转换为PDF,然后使用PDFBox将它们粘贴在一起成一个文件(org.apache.pdfbox.multipdf.PDFMergerUgic)。

    将SVG转换为单页PDF:

    File outputFile = new File(pdfPath);
    SVGConverter converter = new SVGConverter();
    converter.setDestinationType(DestinationType.PDF);
    converter.setSources(new String[] { svgPath });
    converter.setDst(outputFile);
    converter.execute();
    

    一起加入PDF:

    File pdffile = new File(multipagepdfPath);
    PDFMergerUtility pdf = new PDFMergerUtility();
    pdf.setDestinationFileName(pdffile.getPath());
    pdf.addSource(page1pdffile);
    pdf.addSource(page2pdffile);
    pdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
    //The memory settings depend on if you want to use RAM or Temp files.
    

    如果你找到更好的解决方案,请告诉我。我遇到的主要问题是转换器应用程序是Batik中唯一可以转换为pdf并保持大小正确的应用程序。

     类似资料:
    • 我知道如何生成单个超文本标记语言页面。我想知道如何从多个超文本标记语言页面生成的pdf生成单个pdf页面。 例如,有和另一个文件我可以生成单独的pdf文件和分别来自html。我可以将它们写入文件系统,然后像iTextConcatenate示例中那样连接它们。 我只是想知道我是否可以在不将它们写入文件系统的情况下动态地组合此操作。我无法识别丢失的链接

    • 问题内容: 我正在尝试在Django应用程序中使用Python从SVG输入文件生成PDF。 我已经找到了两个可行的解决方案:cairo + rsvg和imagemagick,但是它们都有一个问题:它们具有一些我不想安装在服务器上的奇怪的依赖项,例如DBUS和GTK。 因此,我正在寻求另一种从SVG生成PDF的方法,而不必在服务器上安装所有这些愚蠢的依赖项。 问题答案: 您考虑过svglib吗? 它

    • 本文向大家介绍java生成饼图svg及JFreeChart生成svg图表,包括了java生成饼图svg及JFreeChart生成svg图表的使用技巧和注意事项,需要的朋友参考一下 Jfreechart本身不能生成SVG图形,但是可以借助另外一个东西,辅助生成.好像是这个:batik ,具体代码请看下文 一:Java生成svg饼图,附带了一个标签显示各个颜色代表的部分 二.java生成SVG 3D饼

    • 我想知道是否有一个用于HighChart的Java API(不是导出API),它可以根据提供的参数生成svg,然后可以使用Batik转换为png,而无需靠近HTTP请求。 目前,我能想到的唯一方法是发布到一个带有图表点的虚拟页面,然后导出到SVG并提交到带有Javascript的导出服务,Javascript将其转换为带有蜡染的PNG,然后以图像流的形式返回。 然而,我所需要的只是从数据库中获取由

    • 问题内容: 有人知道使用SAX框架(或类似的东西)和Java编写XML的好教程(或有好的示例)吗?就有用的结果而言,搜索产生的很少。我正在尝试从Android应用程序导出,并希望避免尽可能多的内存开销。 问题答案: 有一种非常有用的技术,可以通过 SAX框架 (不是SAX解析器,而是SAX框架)直接从POJO 生成 XML 。该技术可用于 生成XML文档 。 从任意数据结构生成XML http:/

    • 问题内容: 我意识到之前曾有人问过这个问题(我查看了所有解决方案并尝试了所有解决方案),但我仍在尝试生成一个PDF文件,该文件的页眉和页脚在每个页面上都重复出现。 我在使用R8时尝试了许多不同的方法来使其正常工作,但到目前为止没有任何效果。我测试过的一些方法是https://gist.github.com/626264,使用运行元素和边距框 http://pigeonholdings.com/pr