phantomjs pdf zu stdout

8

Ich versuche verzweifelt, ein von phantomJS generiertes PDF auszugeben, wie hier

Was ich bekomme, ist eine leere PDF-Datei, obwohl sie nicht 0 ist, zeigt sie eine leere Seite an.

%Vor%

Und ich nenne es so: phantomjs rasterize.js http://google.com>test.pdf

Ich habe versucht, /dev/stdout in system.stdout zu ändern, aber nicht Glück. PDF direkt in Datei zu schreiben funktioniert ohne Probleme.

Ich suche nach einer plattformübergreifenden Implementierung, also hoffe ich, dass dies auf nicht-Linux-Systemen erreichbar ist.

    
michaeltintiuc 22.10.2013, 08:40
quelle

3 Antworten

15

Beim Schreiben der Ausgabe in /dev/stdout/ oder /dev/stderr/ unter Windows durchläuft PhantomJS die folgenden Schritte (wie in der Methode render in \ phantomjs \ src \ webpage.cpp ):

  1. In Abwesenheit von /dev/stdout/ und /dev/stderr/ wird ein temporärer Dateipfad zugewiesen.
  2. Rufen Sie renderPdf mit dem temporären Dateipfad auf.
  3. Rendern Sie die Webseite auf diesen Dateipfad.
  4. Lesen Sie den Inhalt dieser Datei in QByteArray .
  5. Rufen Sie QString::fromAscii im Bytearray auf und schreiben Sie in stdout oder stderr .
  6. Löschen Sie die temporäre Datei.

Zunächst habe ich die Quelle für PhantomJS erstellt, aber die Löschung der Datei auskommentiert. Beim nächsten Durchlauf konnte ich die temporäre Datei untersuchen, die sie gerendert hatte, was sich als völlig in Ordnung erwies. Ich habe auch versucht, phantomjs.exe rasterize.js http://google.com > test.png mit denselben Ergebnissen auszuführen. Dies schloss ein Rendering-Problem oder irgendetwas, das speziell mit PDFs zu tun hatte, sofort aus, was bedeutete, dass das Problem damit zusammenhängen musste, wie Daten in stdout geschrieben wurden.

Zu diesem Zeitpunkt hatte ich Verdacht, ob es Text-Encoding-Shenanigans gab. Von früheren Läufen hatte ich sowohl eine gültige als auch eine ungültige Version derselben Datei (in diesem Fall ein PNG).

Unter Verwendung eines C # -Codes habe ich das folgende Experiment ausgeführt:

%Vor%

Beachten Sie, dass ich die ISO-8859-1-Codierung verwendet habe, da QT dies als Standardeinstellung verwendet Kodierung für C-Strings . Wie sich herausstellte, waren alle diese Bytes gleich. Der Zweck dieser Übung bestand darin, zu sehen, ob ich die Kodierungsschritte nachahmen könnte, die dazu führten, dass gültige Daten ungültig wurden.

Für weitere Beweise untersuchte ich \ phantomjs \ src \ system.cpp und \ phantomjs \ src \ filesystem.cpp .

  • In system.cpp enthält die Klasse System unter anderem File -Objekte für stdout , stdin und stderr , die für die Verwendung von UTF-8 encoding.
  • Beim Schreiben in stdout wird die Funktion write des Objekts File aufgerufen. Diese Funktion unterstützt das Schreiben sowohl in Text- als auch in Binärdateien. Wegen der Art und Weise, wie die System -Klasse sie initialisiert, werden alle Schreibvorgänge so behandelt, als würden sie in eine Textdatei gehen.

Also läuft das Problem darauf hinaus: Wir müssen eine binäre Schreiboperation auf stdout durchführen, doch unsere Schreiboperationen werden als Text behandelt und eine Codierung angewendet, die dazu führt, dass die resultierende Datei ungültig wird.

Angesichts des oben beschriebenen Problems sehe ich keinen Weg, wie dies unter Windows so funktioniert, wie Sie es wollen, ohne Änderungen am PhantomJS -Code vorzunehmen. Also hier sind sie:

Diese erste Änderung wird eine Funktion bereitstellen, die wir auf File -Objekten aufrufen können, um explizit einen binären Schreibvorgang auszuführen.

Fügen Sie den folgenden Funktionsprototyp in \phantomjs\src\filesystem.h hinzu:

%Vor%

Und setze seine Definition in \phantomjs\src\filesystem.cpp (der Code für diese Methode stammt von der Methode write in dieser Datei):

%Vor%

Um die Zeile 920 von \phantomjs\src\webpage.cpp sehen Sie einen Codeblock, der folgendermaßen aussieht:

%Vor%

Ändern Sie es zu diesem:

%Vor%

Also, was dieser Code-Ersatz tut, ruft unsere neue binaryWrite -Funktion auf, wird aber durch einen #ifdef Q_OS_WIN32 -Block geschützt. Ich habe es so gemacht, um die alte Funktionalität auf Nicht-Windows-Systemen beizubehalten, die dieses Problem nicht zu zeigen scheinen (oder nicht?). Beachten Sie, dass dieser Fix nur für das Schreiben in stdout gilt - wenn Sie möchten, können Sie ihn immer auf stderr anwenden, aber das ist in diesem Fall nicht so wichtig.

Falls Sie nur eine vordefinierte Binärdatei haben möchten (wer nicht?), können Sie phantomjs.exe mit diesen Korrekturen auf meiner SkyDrive . Meine Version ist ungefähr 19 MB, wohingegen die, die ich vorher heruntergeladen habe, nur ungefähr 6 MB groß war, obwohl ich die Anweisungen hier befolgt habe, also sollte es in Ordnung sein .

    
nick_w 17.01.2014, 11:50
quelle
7

Ja, das stimmt. ISO-8859-1 ist die Standardcodierung für QT, daher müssen Sie der Befehlszeile den erforderlichen Parameter hinzufügen --output-encoding = ISO-8859-1, damit die PDF-Ausgabe nicht erfolgt beschädigt

d.

phantomjs.exe rasterize.js - Ausgangscodierung = ISO-8859-1 & lt; input.html & gt; output.pdf

und rasterize.js sieht so aus (getestet, funktioniert für Unix und Windows)

%Vor%

oder alternativ können Sie die Kodierung mit stdout einstellen und wenn Sie vom UTF-8-Stream lesen, müssen Sie möglicherweise auch die Kodierung für stdin einstellen;

%Vor%     
Pinchy 23.05.2016 00:42
quelle
0

Ist es zwingend erforderlich, das PDF auf stdout auszugeben? Könntest du den Code nicht in:

ändern? %Vor%

und benutze es so:

%Vor%     
Antonio E. 15.01.2014 19:41
quelle

Tags und Links