Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Apache fop -- welche Möglichkeit gibt es um den Fortschritt anzuzeigen (Progressbar)
ich nutze die Bibliothek Apache fop um aus einer großen xml-Datei via xslt eine pdf-Datei zu erzeugen.
Das funktioniert jetzt auch alles wie es soll. Leider dauert es einige Sekunden bis die pdf-Datei generiert wurde.
Gerne würde ich den aktuellen Fortschritt in einem Progressbar oder Progressmonitor sichtbar machen.
Leider finde ich keinen Ansatz dazu. Ich habe mich an die Codebeispiele in der fop-Bibliothek gehalten.
Hat jemand einen Lösungsansatz?
Wie viele Seiten PDF werden eigentlich erzeugt? Selbst bei 1500-1800 Seiten zeige ich nur an: "Bitte haben Sie ein paar Sekunden Geduld, Ihr Dokument wird gerade erstellt." - mit so einem "loading gears"-Gif daunter. Ich denke das dauert nicht länger als 10-15 Sekunden. Darüber bekommt der Nutzer dann eine Mail mit Download-Link für die nächsten 48 Stunden oder auch direkt einen Slot in der Druckerei. Sehr lange darf das aber auch nicht dauern. Stell dir mal vor du hast gerade 10 Nutzer, die so große PDF's erstellen wollen. Dann ist es notwendig so schnell wie möglich den Speicher wieder frei zu bekommen. Auch die Druckerei kostet ganz schön viel Geld, das will man ja nicht für Wartezeit ausgeben.
Mich hat das Thema selbst mal interessiert und ich habe mal etwas herumgespielt. Das Ergebnis will ich hier mal kurz zeigen. Es ist noch nicht perfekt, mehr so ein proof of concept. Die volle Länge würde den Rahmen hier sprengen, also etwas gekürzt. Der Fortschritt wird über eine eigene FOP-Extension: fox:progress getrackt. Das Element wird nicht in PDF umgewandelt, sondern dafür verwendet ein Event für den Fortschritt auszulösen. Der Fortschritt kann dann per Eventlistener abgeholt werden. Ich hoffe der Code + XML/XSL ist weitgehend selbsterklärend. Feedback willkommen.
@Override
protected void initialize() {
if (this.foObjs == null) {
this.foObjs = new HashMap<>();
this.foObjs.put("progress", new ProgressMaker(this.eventBroadcaster));
}
}
}
private static final class ProgressEventListener implements EventListener {
private static final StringBuilder SB = new StringBuilder();
private static final char[] chars = new char[106];
static {
Arrays.fill(chars, '\b');
}
@Override
public void processEvent(final Event event) {
if ("progress".equals(event.getEventID())) {
final String s = (String) event.getParams().get("value");
final int p = Integer.parseInt(s.split("\\.")[0]);
SB.setLength(0);
for (int i = 0; i < 100; i++) {
SB.append(i < p ? '█' : '░');
}
System.out.print(chars);
System.out.print("[" + String.format("%-100s", SB.toString()) + "] " + p + "%");
}
}
private void convertToPDF() throws IOException, FOPException, TransformerException {
final File xsltFile = new File("test.xsl");
final StreamSource xmlSource = new StreamSource(new File("test.xml"));
final FopFactory fopFactory = FopFactory.newInstance(new File(".").toURI());
final FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
final EventBroadcaster eventBroadcaster = foUserAgent.getEventBroadcaster();
eventBroadcaster.addEventListener(new ProgressEventListener());
fopFactory.addElementMapping(new ProgressElementMapping(eventBroadcaster));
try (OutputStream out = new java.io.FileOutputStream("test.pdf")) {
final Fop fop = fopFactory.newFop(org.apache.xmlgraphics.util.MimeConstants.MIME_PDF, foUserAgent, out);
final TransformerFactory factory = TransformerFactory.newInstance();
final Transformer transformer = factory.newTransformer(new StreamSource(xsltFile));
final Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(xmlSource, res);
}
}
public void transform(final String inputXSL, final String inputXML, final String outfile)
throws TransformerException {
final Result out = new StreamResult(outfile);
final StreamSource xml = new StreamSource(inputXML);
final StreamSource xsl = new StreamSource(inputXSL);
final Transformer transformer = TransformerFactory.newInstance().newTransformer(xsl);
transformer.transform(xml, out);
}