PhantomJS: Eksport PDF do stdout
Czy istnieje sposób na uruchomienie funkcji eksportu PDF w PhantomJS bez określania pliku wyjściowego za pomocą .rozszerzenie pdf? Chcemy użyć stdout
do wyświetlenia pliku PDF.
4 answers
Jak zauważył Niko, możesz użyć renderBase64()
, aby renderować stronę internetową do bufora obrazu i zwrócić wynik jako zakodowany łańcuch base64.
ale na razie będzie to działać tylko dla PNG, JPEG i GIF.
Aby napisać coś ze skryptu phantomjs na stdout wystarczy użyć API systemu plików.
Używam czegoś takiego do zdjęć:
var base64image = page.renderBase64('PNG');
var fs = require("fs");
fs.write("/dev/stdout", base64image, "w");
Nie wiem, czy Format PDF dla renderBase64()
będzie w przyszłej wersji phanthomjs, ale jako obejście coś w tym stylu może praca dla Ciebie:
page.render(output);
var fs = require("fs");
var pdf = fs.read(output);
fs.write("/dev/stdout", pdf, "w");
fs.remove(output);
Gdzie output
jest ścieżką do pliku pdf.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-16 15:58:16
Możesz wypisać bezpośrednio na stdout bez potrzeby używania pliku tymczasowego.
page.render('/dev/stdout', { format: 'pdf' });
Zobacz tutaj aby dowiedzieć się, kiedy to zostało dodane.
Jeśli chcesz pobrać HTML ze standardowego wejścia i wysłać plik PDF do standardowego wyjścia, zobacz tutaj
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:40
Przepraszam za niezwykle długą odpowiedź; mam wrażenie, że będę musiał odwoływać się do tej metody kilkadziesiąt razy w życiu, więc napiszę "jedna odpowiedź, aby rządzić nimi wszystkimi". Najpierw będę paplał trochę o plikach, deskryptorach plików, (nazwanych) rurach i przekierowaniu wyjścia, a następnie odpowiem na twoje pytanie.
Rozważ ten prosty program C99:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
if (argc < 2) {
printf("Usage: %s file_name\n", argv[0]);
return 1;
}
FILE* file = fopen(argv[1], "w");
if (!file) {
printf("No such file: %s\n", argv[1]);
return 2;
}
fprintf(file, "some text...");
fclose(file);
return 0;
}
Bardzo proste. Pobiera argument (nazwę pliku) i drukuje do niego tekst. Couldn ' t be any prościej.
Skompiluj go z clang write_to_file.c -o write_to_file.o
lub gcc write_to_file.c -o write_to_file.o
.
Teraz uruchom ./write_to_file.o some_file
(który wyświetla się w some_file
). Następnie uruchom cat some_file
. Wynik, zgodnie z oczekiwaniami, to some text...
Teraz bądźmy bardziej wyszukani. Wpisz (./write_to_file.o /dev/stdout) > some_file
w terminalu. Prosimy program o zapis na jego standardowe wyjście (zamiast zwykłego pliku), a następnie przekierowujemy stdout
na some_file
(używając > some_file
). Aby to osiągnąć, mogliśmy użyć dowolnego z następujących elementów:]}
(./write_to_file.o /dev/stdout) > some_file
, które oznacza " użyciestdout
"(./write_to_file.o /dev/stderr) 2> some_file
, co oznacza " użyjstderr
, i przekieruj go za pomocą2>
"(./write_to_file.o /dev/fd/2) 2> some_file
, który jest taki sam jak powyżej; {[30] } jest trzecim deskryptorem pliku przypisanym domyślnie do procesów uniksowych (postdin
istdout
)(./write_to_file.o /dev/fd/5) 5> some_file
, co oznacza " użyj szóstego deskryptora pliku i przekieruj go dosome_file
"
W przypadku, gdy nie jest jasne, używamy uniksowego potoku zamiast rzeczywistego pliku (wszystko jest plikiem w Unix przecież). Możemy robić różne fantazyjne rzeczy za pomocą tego potoku: zapisywać go do pliku lub zapisywać do nazwanego potoku i udostępniać go między różnymi procesami.
Teraz stwórzmy nazwaną rurę:
mkfifo my_pipe
Jeśli wpiszeszls -l
teraz zobaczysz:
total 32
prw-r--r-- 1 pooriaazimi staff 0 Jul 15 09:12 my_pipe
-rw-r--r-- 1 pooriaazimi staff 336 Jul 15 08:29 write_to_file.c
-rwxr-xr-x 1 pooriaazimi staff 8832 Jul 15 08:34 write_to_file.o
Zwróć uwagę na p na początku drugiej linii. Oznacza to, że my_pipe
jest (nazwaną) rurą.
A teraz określ, co chcemy zrobić z naszą rurą:
gzip -c < my_pipe > out.gz &
To znaczy: gzip
to, co umieściłem wewnątrz {[39] } i zapisz wyniki w out.gz
. &
na końcu prosi powłokę o uruchomienie tego polecenia w tle. Dostaniesz coś w stylu [1] 10449
i kontrola wróci do terminala.
Następnie, po prostu przekieruj wyjście naszego programu C do tej rury:
(./write_to_file.o /dev/fd/5) 5> my_pipe
Lub
./write_to_file.o my_pipe
Dostaniesz
[1]+ Done gzip -c < my_pipe > out.gz
Co oznacza, że komenda gzip
została zakończona.
Teraz zrób jeszcze jedno ls -l
:
total 40
prw-r--r-- 1 pooriaazimi staff 0 Jul 15 09:14 my_pipe
-rw-r--r-- 1 pooriaazimi staff 32 Jul 15 09:14 out.gz
-rw-r--r-- 1 pooriaazimi staff 336 Jul 15 08:29 write_to_file.c
-rwxr-xr-x 1 pooriaazimi staff 8832 Jul 15 08:34 write_to_file.o
Udało nam się gzip
SMS!
Wykonaj gzip -d out.gz
aby zdekompresować ten plik gzip
ed. Zostanie on usunięty i utworzony nowy plik (out
). cat out
dostaje nas:
some text...
Tego się spodziewaliśmy.
Nie zapomnij wyjąć rury rm my_pipe
!
Teraz wracamy do PhantomJS.
Jest to prosty skrypt PhantomJS (render.coffee
, napisany w CoffeeScript), który pobiera dwa argumenty: adres URL i nazwę pliku. Ładuje adres URL, renderuje go i zapisuje do podanego pliku nazwa:
system = require 'system'
renderUrlToFile = (url, file, callback) ->
page = require('webpage').create()
page.viewportSize = { width: 1024, height : 800 }
page.settings.userAgent = 'Phantom.js bot'
page.open url, (status) ->
if status isnt 'success'
console.log "Unable to render '#{url}'"
else
page.render file
delete page
callback url, file
url = system.args[1]
file_name = system.args[2]
console.log "Will render to #{file_name}"
renderUrlToFile "http://#{url}", file_name, (url, file) ->
console.log "Rendered '#{url}' to '#{file}'"
phantom.exit()
Teraz wpisz phantomjs render.coffee news.ycombinator.com hn.png
W Terminalu, aby renderować pierwszą stronę Wiadomości hakerskich do pliku hn.png
. Działa zgodnie z oczekiwaniami. Tak jak phantomjs render.coffee news.ycombinator.com hn.pdf
.
(phantomjs render.coffee news.ycombinator.com /dev/fd/5) 5> hn.pdf
To nie działa... : (Dlaczego? Ponieważ, jak stwierdzono w instrukcji PhantomJS :
Render (nazwa pliku)
Renderuje stronę internetową do bufora obrazu i zapisuje ją jako określony plik.
Obecnie format wyjściowy jest automatycznie ustawiany na podstawie pliku przedłużenie. Obsługiwane formaty to PNG, JPEG i PDF.
Nie udaje się, po prostu dlatego, że ani /dev/fd/2
, ani /dev/stdout
nie kończą się na .PNG
, itd.
Ale bez strachu, nazwane rury mogą Ci pomóc!
Utwórz inną nazwę rury, ale tym razem użyj rozszerzenia .pdf
:
mkfifo my_pipe.pdf
Teraz powiedz to po prostu cat
its inout to hn.pdf
:
cat < my_pipe.pdf > hn.pdf &
Następnie uruchom:
phantomjs render.coffee news.ycombinator.com my_pipe.pdf
I oto piękna hn.pdf
!
Oczywiście chcesz zrobić coś bardziej wyrafinowanego, co po prostu cat
w wyjściu, ale jestem pewien, że teraz jest jasne, co powinieneś zrobić:)
TL; DR:
-
Utwórz nazwaną rurę, używając ".rozszerzenie pliku pdf " (tak aby PhantomJS myślał, że jest to plik PDF):
mkfifo my_pipe.pdf
-
Rób co chcesz z zawartością pliku, na przykład:
cat < my_pipe.pdf > hn.pdf
Które po prostu
cat
S to dohn.pdf
W PhantomJS render do tego pliku / rury.
-
Później powinieneś usunąć rurę:
rm my_pipe.pdf
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-28 00:35:24
Nie wiem, czy to rozwiąże twój problem, ale możesz również sprawdzić nową metodę renderBase64()
dodaną do PhantomJS 1.6: https://github.com/ariya/phantomjs/blob/master/src/webpage.cpp#L623
Niestety, funkcja nie jest jeszcze udokumentowana na wiki: /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-15 09:07:24