2012-04-22 4 views
12

Ich muss eine 100+ Seiten PDF-Dokumente generieren. Der Prozess benötigt eine Menge zu verarbeitender Daten und die gesamte Generierung benötigt mehr Zeit und Speicher, die ich geben kann.So erstellen Sie PDF-Dokumente Seite für Seite in Hintergrundaufgaben auf App Engine

Ich habe ein paar verschiedene Methoden ausprobiert, obwohl mein Weg zu hacken:

verschmelzenden Mit variierendem Ergebnis habe ich es funktioniert, aber es ist langsam und benötigt mehr Speicher als es sollte (manchmal trifft es auf Instance Sof) t Speichergrenze). Zur Zeit erzeuge ich einige Abschnitte in verschiedenen Aufgaben, die jeweils im Blobstore gespeichert werden und diese mit pyPdf zusammenführen, aber es erstickt bei größeren Dokumenten.

Das Dokument, das ich generiere, ist nicht so kompliziert, hauptsächlich Tabellen und Text, keine internen Verweise, kein Inhaltsverzeichnis, nichts, was den Rest des Dokuments wissen sollte. Ich kann mit Platypus für Layout arbeiten und ich brauche kein schickes Dokument Aussehen oder HTML2PDF Konvertierung.

Ziel ist es, das Dokument so schnell zu generieren, wie es der Datenspeicher erlaubt. Parallele Seitengenerierung wäre nett, aber nicht erforderlich.

Ich dachte an die Seite-für-Seite-Generierung mit blobstore files api, wo jede Aufgabe eine einzelne Seite erzeugen würde und die letzte Aufgabe würde blobstore Datei finalisieren damit es lesbar. Aber ich kann anscheinend nicht finden, wie man die Generierung pausiert, partielle PDF-Dateien im Stream speichert und die Generierung mit diesem Stream wieder aufnimmt, um die nächste Seite in einer anderen Aufgabe zu erzeugen.

Also meine Frage ist:

Wie auf GAE erzeugt eine größer als ein paar Seiten PDF-Dokument, die Erzeugung zwischen Aufgabenanfragen Aufspaltung, dann speichern Sie das resultierende Dokument im Blobstore?

Wenn das Generierungssplitting mit reportlab nicht möglich ist, wie kann man dann den Platzbedarf beim Zusammenführen verschiedener PDF-Dokumente minimieren, damit es den durch die GAE-Aufgabenanforderung gesetzten Grenzen entspricht?

UPDATE: Alternativen zur Konvertierung API sehr geschätzt.

2. UPDATE Die Conversion-API wird außer Betrieb genommen, daher ist dies keine Option.

3. UPDATE Kann Pileline oder MapReduce APIs hier helfen?

+0

Haben Sie eine Möglichkeit, die Quelldaten in Seitengrößen zu teilen, ohne die eigentliche Konvertierung durchzuführen? Wenn dies der Fall ist, könnten Sie eine Funktion schreiben, die replortlab verwendet, um einzelne Seiten zu generieren und 'multiprocessing.Pool.map' zu verwenden, um diese parallel über eine Liste von Chunks aller Ihrer Eingaben auszuführen. Als letzten Schritt verwenden Sie pyPdf, um die Seiten zu einem einzigen Dokument zusammenzuführen. –

+0

Ich mache schon etwas ähnliches ohne viel Erfolg, die Verschmelzung dauert zu viel Zeit, um während der Aufgabe (muss weniger als 10 min sein) für einige Dokumente zu beenden. Vielleicht mache ich es falsch, trotzdem möchte ich ein Codebeispiel, wie es richtig gemacht wird. –

+1

Schneller Satz von großen Dokumenten klingt wie ein Auftrag für TeX (möglicherweise mit den LaTeX- oder conTeXt-Makropaketen). Sie müssten das jedoch auf einem separaten Server ausführen. –

Antwort

1

Werfen Sie einen Blick auf die neue Conversion API: https://developers.google.com/appengine/docs/python/conversion/overview

+0

Es gibt ein Limit von 60s, wie groß sind die Dokumente, die du damit generiert hast? Ich denke, die Person vor mir hat das versucht und keine guten Ergebnisse erzielt. Diese API ist ziemlich einfach: Wie fügen Sie beispielsweise Seitenumbrüche ein? –

+0

Wenn Sie es in einer Aufgabenwarteschlange ausführen, haben Sie 10 Minuten Zeit: https://developers.google.com/appengine/articles/deferred –

+0

Sagen Sie, dass [maximale Frist, in der 60s eine Konvertierungsanfrage gestellt wurde] (https: // developers. google.com/appengine/docs/python/conversion/overview#Limits) wird deaktiviert, wenn die Conversion-API von einer Aufgabe verwendet wird? –

1

I wkhtmltopdf auf App Engine empfiehlt die Installation. Wkhtmltopdf ist ein Kommandozeilenwerkzeug, um HTML in PDF zu rendern.

Erstellen Sie die HTML-Dateien und konvertieren Sie sie dann einzeln in pdf mit wkhtmltopdf.

Unter Windows können Sie verwenden (unter Linux-basierten Systemen ist es so ähnlich):

def create_pdf(in_html_file=None, out_pdf_file=None, quality=None): 
    pathtowk = 'C:/wkhtmltopdf/bin/wkhtmltopdf.exe {0} {1} {2}'  

    if quality == 1: # super quality no compression 
     args_str = '--encoding utf-8 --disable-smart-shrinking --no-pdf-compression --page-size A4 --zoom 1 -q -T 15.24mm -L 25.4mm -B 20.32mm -R 33.02mm' 
    elif quality == 2: # moderate quality some compression 
     args_str = '--encoding utf-8 --disable-smart-shrinking --page-size A4 --zoom 1 -q -T 15.24mm -L 25.4mm -B 20.32mm -R 33.02mm' 
    else: # poor quality max compression 
     args_str = '--encoding utf-8 --page-size A4 --zoom 1 -q -T 15.24mm -L 25.4mm -B 20.32mm -R 33.02mm' 

    os.system(pathtowk.format(args_str, in_html_file, out_pdf_file)) 

Alternativ können Sie subprocess.call(pathtowk.format(args_str, in_html_file, out_pdf_file)) verwenden wkhtmltopdf (es ist besser, meiner Meinung nach) auszuführen.

Wenn der Konvertierungsprozess abgeschlossen ist, verwenden Sie PyPdf2 zum Zusammenführen der generierten PDFs in eine einzelne Datei.

Verwandte Themen