web-dev-qa-db-fra.com

Convertir SVG en PDF

Comment convertir un fichier SVG en un PDF par programmation? (J'ai besoin de modifier le SVG à certains égards avant de générer le PDF donc simplement la convertir à l'aide d'un outil ne sera pas suffisante.)

Idéalement, utiliser Java mais Perl ou PHP serait bien aussi.

Évidemment, je considère essentiellement Apache FOP et Batik avec Java. Cependant, peu importe combien de temps je recherche, je ne trouve pas une simple introduction sur la façon de le faire. Des choses comme SVGConverter ont des descriptions comme "Définit l'interface pour les classes capables de convertir une partie ou la totalité d'un GraphicContext", mais je ne sais pas vraiment ce que cela signifie.

J'ai le sentiment qu'il doit y avoir une API pour le faire tout simplement, fournie par FOP ou Batik, mais je ne suis tout simplement pas en mesure de la trouver pour le moment (ou peut-être qu'elle n'existe vraiment pas).

En termes de fonctionnalités SVG prises en charge dont j'ai besoin, le fichier a des chemins qui sont remplis de quelques gradients linéaires.

Idéalement, si je pouvais transmettre le SVG en tant que document DOM, ce serait idéal; alors je chargerais mon modèle de fichier SVG, le changerais comme spécifié par l'utilisateur, puis générerais le PDF.

28
Adrian Smith

Merci à Adrian d'avoir montré comment l'API matricielle Batik est censée être utilisée. Cependant, j'avais besoin d'une solution plus légère --- je ne peux pas écrire dans des fichiers temporaires et je veux moins de dépendances. Donc, à partir des méthodes qu'il a indiquées, j'ai trouvé un moyen d'accéder au code de niveau inférieur pour effectuer la conversion et rien d'autre.

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);
    }
}

Les commandes de compilation et d'exécution sont

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

Le point important est que TranscoderInput et TranscoderOutput peut fonctionner avec n'importe quel InputStream et OutputStream , pas seulement les flux de fichiers. Notez que l'un des constructeurs prend un org.w3c.dom.Document , ce qui signifie que vous n'avez même pas besoin de sérialiser un DOM SVG en une chaîne SVG, économisant ainsi une étape supplémentaire.

Cette version n'écrit également rien sur stdout/stderr, contrairement à l'API de haut niveau.

Pour la sortie JPEG, PNG ou TIFF, remplacez org.Apache.fop.svg.PDFTranscoder avec org.Apache.batik.transcoder.image.JPEGTranscoder, PNGTranscoder ou TIFFTranscoder (notez que ces formats raster sont dans un package différent).

(Je ne sais pas trop comment Java trouve le org.Apache.batk.transcoder.* et org.Apache.fop.svg.PDFTranscoder classes, car je ne les vois pas dans les batik-rasterizer.jar.)

Modifier:

Bien que la simple compilation en ligne de commande fonctionne avec le batik-rasterizer.jar seulement, il fait une sorte de magie de chargeur de classe pour trouver toutes les classes nécessaires. Dans un cas plus réaliste (construction d'un projet avec Ant), vous devez trouver les classes à la main. Ils peuvent être trouvés dans batik-1.7.Zip de le projet Batik et fop-1.1.Zip de le projet FOP . Depuis Batik, vous devez compiler avec batik-transcoder.jar et courir avec

  • 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

Depuis FOP, vous devez compiler avec fop.jar et courir avec

  • fop.jar
  • avalon-framework-4.2.0.jar
  • xmlgraphics-commons-1.5.jar
18
Jim Pivarski

J'ai finalement réussi à trouver les lignes de code appropriées pour résoudre ce problème en utilisant Batik .

Vous devez avoir le fichier SVG et le fichier PDF) sous forme de fichiers sur le disque, c'est-à-dire que je n'ai pas trouvé de moyen de le faire en mémoire (j'écris un servlet HTTP donc j'ai aucun besoin intrinsèque d'écrire quoi que ce soit sous forme de fichier, idéalement je diffuserais le résultat sur le client HTTP.) J'ai utilisé File.createTemporaryFile pour créer un fichier pour vider mon SVG dans un fichier, et pour le résultant PDF à écrire.

Les lignes que j'ai utilisées sont donc les suivantes:

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();

Et j'ai les fichiers JAR suivants (recherchez à l'aide de Google pour trouver les projets et les télécharger):

  • 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
5
Adrian Smith

vous aurez besoin d'un libray pour le rendu des svg et pdf. Je recommande salamandre SVG pour le premier, et iText pour le second. Avec la salamandre svg, vous pouvez lire le svg et créer un objet image, et avec itext vous pouvez écrire cette image dans un pdf.

4
S E

J'utilise Altsoft Xml2PDF. Si j'ai bien compris tous vos besoins et exigences, vous feriez mieux d'essayer leur version serveur de Xml2PDF.

1
Nat

Tout ce dont vous avez besoin est de fantômes. Vous n'avez pas besoin du tout lourd Batik pour cela; atteignez simplement un point où vous pouvez exécuter phantomjs, en appelant rasterize.js, en utilisant l'url du pdf comme source et un emplacement comme sortie. Selon ce que vous voulez faire avec le .pdf, vous n'avez même pas besoin de Java.

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

Regardez la partie commençant par "A côté du format PNG, PhantomJS prend en charge JPEG, GIF et PDF".

1
Sandy Simonton