0

I want to use Ghostscript command within PHP without writing the input or output in files.

$cmd = "gs -sOutputFile=%stdout% -sDEVICE=pdfwrite -dJOBSERVER -";
$descriptorspec = array(0 => array("pipe", "r"),1 => array("pipe", "w"));
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
 fwrite($pipes[0], file_get_contents('file.ps'));
 fclose($pipes[0]);
 $pdf_content = stream_get_contents($pipes[1]);
 fclose($pipes[1]);
 $return_value = proc_close($process);
 header('Content-type: application/pdf');
 header('Content-Disposition: attachment; filename="output.pdf"');
 echo $pdf_content;
}

Writting to STDOUT works well, but I cannot get the STDIN to work. If replacing the command line to

$cmd = "gs -sOutputFile=%stdout% -sDEVICE=pdfwrite -dNOSAFER file.ps";

it works well, but it doesn't when trying to read the input from $pipes[0]. Where did I go wrong?

asked Jan 14, 2022 at 6:27
4
  • Please tell us what you observe when running a minimal reproducible example. In particular, the question is whether this is specific to GS even. Commented Jan 14, 2022 at 8:49
  • @UlrichEckhardt the code is itself a minimal reproducible example, as you can run it with any input PS file (I deliberately used file_get_contents instead of the direct variable). The output is a corrupt PDF. I am not sure how I can report the error since the output contains binary data. What can be the alternative to GS here? Commented Jan 14, 2022 at 8:59
  • 1
    Try e.g. tee. Compare what you put in and what came out. Question is whether GS is the cause of the problem or the way you redirect stdin/stdout. BTW: 2 should be stderr, but you don't supply a pipe for that. Is that intended? Don't you miss (possibly important) error info from that? Commented Jan 14, 2022 at 10:05
  • @UlrichEckhardt no, the problem is not GS. I think the problem lies where PHP writes to php://stdin. I think the stdin read by GS is not what was expected (possible an opening or ending character). I dropped the third pipeline of stderr for the sake of simplicity. I was unable to catch any error there. Commented Jan 14, 2022 at 10:46

1 Answer 1

1

You need to supply '-' as the input filename. So for example:

gs -sDEVICE=pdfwrite -o out.pdf - < /ghostpdl/examples/golfer.eps

Tells Ghostscript to take input from stdin, and directs the content of that file into stdin.

However, for PDF input if you send the input on stdin it is written to a temporary file on disk and then processed, because PDF requires random access to the file, it isn't a streamable format.

For PDF output I would very much advise against writing to stdout. There is already one feature which requires the code to seek inside the output file, and in future there may be more. Obviously that won't be possible if you write the output to stdout so I'd really recommend you don't do that.

answered Jan 14, 2022 at 8:11
Sign up to request clarification or add additional context in comments.

3 Comments

Then, what is the difference between gs -sDEVICE=pdfwrite -o out.pdf - < in.ps and gs -sDEVICE=pdfwrite -o out.pdf -dNOSAFER in.ps. And how does cat in.ps | gs -sDEVICE=pdfwrite -o out.pdf work? I didn't catch the drawback of echoing the output instead of writing it to a file.
Writing the output to a file means that the file pointer can be repositioned and data overwritten. One feature already requires this, future features may do as well. If you output to stdout then the code cannot rewind the file pointer, so that feature won't work (worse it may result in a broken PDF file). Using "gs - < in.ps" and "gs in.ps" is equivalent. I don't see how using | works at all in the example you quote and I'm not interested enough to investigate whether it does.
Actually... If you just start up Ghostscript then you will enter the interactive PostScript prompt. I imagine that (on Linux at least) that will read from stdin, so yeah that will work, but mostly by co-incidence, and I don't think it will work on (eg) Windows. Also possibly not in the environment you are using.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.