拡張子が .pdf の出力ファイルを指定せずに、PhantomJS で PDF エクスポート機能をトリガーする方法はありますか? stdout
PDF出力に使用したいと思います。
4 に答える
一時ファイルを必要とせずに、stdout に直接出力できます。
page.render('/dev/stdout', { format: 'pdf' });
これが追加されたときの履歴については、こちらを参照してください。
標準入力から HTML を取得し、PDF を標準出力に出力する場合は、こちらを参照してください。
非常に長い回答でごめんなさい。私は人生でこの方法を数十回参照する必要があると感じているので、「それらすべてを支配するための1つの答え」を書きます。まず、ファイル、ファイル記述子、(名前付き)パイプ、および出力リダイレクトについて少し説明してから、質問に答えます。
この単純な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;
}
非常に簡単です。引数(ファイル名)を取り、それにテキストを出力します。これ以上簡単なことはありません。
clang write_to_file.c -o write_to_file.o
またはでコンパイルしgcc write_to_file.c -o write_to_file.o
ます。
次に、を実行します./write_to_file.o some_file
(に出力されsome_file
ます)。次に、を実行しcat some_file
ます。結果は、予想通り、some text...
それでは、もっと凝ったものにしましょう。ターミナル(./write_to_file.o /dev/stdout) > some_file
に入力します。プログラムに(通常のファイルではなく)標準出力に書き込むように要求し、それstdout
をsome_file
(を使用して)にリダイレクトします> some_file
。これを実現するために、次のいずれかを使用できます。
(./write_to_file.o /dev/stdout) > some_file
、これは「使用stdout
」を意味します(./write_to_file.o /dev/stderr) 2> some_file
、これは「を使用しstderr
、を使用してリダイレクトする2>
」ことを意味します(./write_to_file.o /dev/fd/2) 2> some_file
、これは上記と同じです。stderr
デフォルトでUnixプロセスに割り当てられる3番目のファイル記述子です(stdin
およびの後stdout
)(./write_to_file.o /dev/fd/5) 5> some_file
、これは「6番目のファイル記述子を使用してリダイレクトする」ことを意味しsome_file
ます
明確でない場合は、実際のファイルの代わりにUnixパイプを使用しています(結局のところ、すべてがUnixのファイルです)。このパイプを使用して、あらゆる種類の凝ったことを行うことができます。ファイルに書き込むか、名前付きパイプに書き込んで、異なるプロセス間で共有します。
それでは、名前付きパイプを作成しましょう。
mkfifo my_pipe
ここで入力ls -l
すると、次のように表示されます。
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
2行目の先頭のpに注意してください。それはmy_pipe
(名前付き)パイプであることを意味します。
次に、パイプで何をしたいかを指定しましょう。
gzip -c < my_pipe > out.gz &
つまりgzip
、私が中に入れmy_pipe
て結果をに書き込んだものですout.gz
。&
最後に、はシェルにこのコマンドをバックグラウンドで実行するように要求します。次のようなものが表示[1] 10449
され、コントロールがターミナルに戻ります。
次に、Cプログラムの出力をこのパイプにリダイレクトするだけです。
(./write_to_file.o /dev/fd/5) 5> my_pipe
または
./write_to_file.o my_pipe
あなたが得るでしょう
[1]+ Done gzip -c < my_pipe > out.gz
これは、gzip
コマンドが終了したことを意味します。
今、別のことをしなさい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
gzip
テキストの編集に成功しました。
実行gzip -d out.gz
して、このgzip
edファイルを解凍します。削除され、新しいファイル(out
)が作成されます。cat out
私たちを取得します:
some text...
それが私たちが期待したことです。
rm my_pipe
パイプを!で取り外すことを忘れないでください。
PhantomJSに戻ります。
render.coffee
これは、URLとファイル名の2つの引数を取る単純なPhantomJSスクリプト( CoffeeScriptで記述)です。URLをロードしてレンダリングし、指定されたファイル名に書き込みます。
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()
次に、ターミナルに入力phantomjs render.coffee news.ycombinator.com hn.png
して、HackerNewsのフロントページをファイルにレンダリングしますhn.png
。期待どおりに動作します。ですphantomjs render.coffee news.ycombinator.com hn.pdf
。
以前にCプログラムで行ったことを繰り返しましょう。
(phantomjs render.coffee news.ycombinator.com /dev/fd/5) 5> hn.pdf
それは動作しません...:(なぜですか?なぜなら、PhantomJSのマニュアルに記載されているように:
render(fileName)
Webページを画像バッファにレンダリングし、指定されたファイルとして保存します。
現在、出力形式はファイル拡張子に基づいて自動的に設定されます。サポートされている形式は、PNG、JPEG、およびPDFです。
失敗するのは、単に、などで終わら/dev/fd/2
ないからです。/dev/stdout
.PNG
しかし、恐れることはありません。名前付きパイプが役に立ちます。
別の名前付きパイプを作成しますが、今回は拡張子を使用します.pdf
:
mkfifo my_pipe.pdf
さて、それを単にcat
そのインアウトに伝えてくださいhn.pdf
:
cat < my_pipe.pdf > hn.pdf &
次に、以下を実行します。
phantomjs render.coffee news.ycombinator.com my_pipe.pdf
そして、美しいものを見よhn.pdf
!
明らかに、出力を実行するだけでなく、より洗練された何かを実行したいのですcat
が、今、何をすべきかが明確になっていると確信しています:)
TL; DR:
「.pdf」ファイル拡張子を使用して名前付きパイプを作成します(したがって、PhantomJSをだましてPDFファイルだと思い込ませます)。
mkfifo my_pipe.pdf
次のように、ファイルの内容でやりたいことは何でもします。
cat < my_pipe.pdf > hn.pdf
cat
これは単にhn.pdf
PhantomJSで、このファイル/パイプにレンダリングします。
後で、パイプを削除する必要があります。
rm my_pipe.pdf
Niko が指摘したrenderBase64()
ように、Web ページをイメージ バッファにレンダリングし、結果を base64 でエンコードされた文字列として返すために使用できます。
ただし、現時点では、これは PNG、JPEG、および GIF でのみ機能します。
phantomjs スクリプトから stdout に何かを書き込むには、ファイルシステム API を使用するだけです。
画像には次のようなものを使用します:
var base64image = page.renderBase64('PNG');
var fs = require("fs");
fs.write("/dev/stdout", base64image, "w");
renderBase64()
のPDF形式がphanthomjsの将来のバージョンに含まれるかどうかはわかりませんが、回避策として、これらの行に沿った何かがうまくいくかもしれません:
page.render(output);
var fs = require("fs");
var pdf = fs.read(output);
fs.write("/dev/stdout", pdf, "w");
fs.remove(output);
output
PDFファイルへのパスはどこにありますか。
それがあなたの問題に対処するかどうかはわかりませんが、renderBase64()
PhantomJS 1.6 に追加された新しいメソッドを確認することもできます: https://github.com/ariya/phantomjs/blob/master/src/webpage.cpp#L623
残念ながら、この機能はまだ wiki に記載されていません :/