Solved

Using GhostScript to create PDF files - Where do I start?

Posted on 2006-07-18
19
719 Views
Last Modified: 2013-12-03
Hi guys,

I have been given the task of finding out how to convert verious documents to PDF using PHP. We have a PHP server ready and waiting and I was reading an article that showed me how to create a PDF from a PostScript file using GhostScript.

I have followed it through, however there was no information on howto actually install GhostScript and get it to work with PHP.

I have looked at the installation guide that is provided with Ghostscript, however this seems to just be an application and command line interpreter.

Can someone help me as I have no idea where to start. How do I install GS on our server so I can use PHP's exec() function to convert the PS file to PDF?

Just for completeness the article showed this code which is what I am using:

================================================================================================
<?php
// Turn on error reporting
error_reporting(E_ALL);

// Create a page with a message and abort the script (error reporting for the user)
function print_message($s)
{
      die('<html><body><h1>Warning!</h1>'.$s.'</body></html>');
}

// Check the file was uploaded
if(!count ($_FILES || $_FILES['infile']['error'] || strcmp($_FILES['infile']['type'], 'application/postscript')))
      {print_message('No file uploaded or ipload error!');}

// Try running the file through Ghostscript
exec('gs -sDEVICE=pdfwrite -r300 -sOutputFile='.$_FILES['infile']['tmp_name'].'.pdf -dNOPAUSE -dBATCH'.$_FILES['infile']['tmp_name'], $a, $n);

if($n)
      {print_message('Unable to convert file. Please ensure that you have used the proper format and try again.');}

// Output the headers to tell the browser what type of file is being outputted, how long it is and how we want it displayed
header('Content-Type: application/pdf');
header('Content-Disposition: filename="'.$_FILES['infile']['name'].'.pdf%20"');
header('Content-Length: '.filesize($_FILES['infile']['tmp_name'].'.pdf'));

// Dump the PDF file and delete it from the PHP folder
readfile($_FILES['infile']['tmp_name'].'pdf');
unlink($_FILES['infile']['tmp_name'].'pdf');
?>
================================================================================================

As you can see PHP's exec() function simply calls 'gs' to invoke the GhostScript application......HOW??!?!

Any help would be appreciated - please dont just provide links....I really need someone to explain how to do this.

Thanks,
MOZZER
0
Comment
Question by:nikez2k4
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 9
19 Comments
 
LVL 1

Author Comment

by:nikez2k4
ID: 17131101
Any ideas guys???

MOZ
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17144988
Ah.

Where is gs actually installed? exec is not going to use the PATH to locate the program for you.

So, if GS is in C:\Program Files\GhostScript\bin\gs.exe, then ...

exec('"C:/Program Files/GhostScript/bin/gs.exe" -sDEVICE=pdfwrite -r300 -sOutputFile='.$_FILES['infile']['tmp_name'].'.pdf -dNOPAUSE -dBATCH'.$_FILES['infile']['tmp_name'], $a, $n);



Can you ...

replace exec with echo and then exit on the next line. What are you trying to execute?
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17144993
Ahh i get ya - hold on i'll try that now :)

MOZ
0
Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17144996
If the filenames have spaces in them this is going to be a REAL issue.

There is a bug in windows CMD that only allow 1 set of double quotes.

Nothing directly that PHP can do.

The solution is to build a .BAT file containing the complete statement with all the quotes and then use exec() to run that batch file.

That works fine.
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17152598
Hmmm - it seems to work....as it doesnt just send me a warning now.

However it just sits there and doesnt even time out - it's as if Ghostscript is waiting for something.

I can't find a gs.exe application in the version i downloaded (latest) - but there is a command line version....maybe that's the problem. Any ideas?

The exec() script i am using now is:

exec('"C:\Program Files\gs\gs8.54\bin\gswin32c.exe" -sDEVICE=pdfwrite -r300 -sOutputFile='.$_FILES['infile']['tmp_name'].'.pdf -dNOPAUSE -dBATCH'.$_FILES['infile']['tmp_name'], $a, $n);

MOZ
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17152610
Can you replace

exec( ..... );

with

echo ...;

to see what the actual command you are executing is.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17152630
Remember to convert / to \\ for windows files. $_FILES will have / in them which is no good for the cli.

Personally, I would construct the command as a string and use ...

<?php
// just before your exec.
$s_command_line = <<<END_CLI
C:/Progra~1/gs/gs8.54/bin/gswin32c.exe -sDEVICE=pdfwrite -r300 -sOutputFile={$_FILES['infile']['tmp_name']}.pdf -dNOPAUSE -dBATCH {$_FILES['infile']['tmp_name']}
END_CLI;

echo "Before : $s_command_line\n";

$s_command_line = str_replace(array("\\", "/"), DIRECTORY_SEPARATOR, $s_command_line);

echo "After : $s_command_line\n";

exec($s_command_line, $a_results, $i_level);

echo 'Results : ' . var_export($a_results, True) . ' ' . $i_level;
?>
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17152745
I will have a go at that in a second mate - I just want to try somehting else first.

I have been messing around with the COM object for Microsoft Word and have managed to create a Word document and save it to a specified location.

What i would like to do is open a document using COM and print the file to a file (Postscript printer I have set up). I have written a macro that does this and it works perfectly, however it still asks for the filename. I have taken the VBA code from the macro so maybe I could convert the process into PHP and use COM to print the document to create a Postscript file?

Here is the code:

****************************************************************************************
Sub PrintPostscript()
'
' PrintPostscript Macro
' Macro recorded 21/07/2006 by MARSHALL
'
    Application.PrintOut FileName:="", Range:=wdPrintAllDocument, Item:= _
        wdPrintDocumentContent, Copies:=1, Pages:="", PageType:=wdPrintAllPages, _
        ManualDuplexPrint:=False, Collate:=True, Background:=True, PrintToFile:= _
        False, PrintZoomColumn:=0, PrintZoomRow:=0, PrintZoomPaperWidth:=0, _
        PrintZoomPaperHeight:=0
End Sub
****************************************************************************************

Any ideas?

MOZZER
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17152819
// Print it
$word->PrintOut();

All the parameters are defaulted and this works on my version 11.0
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17152837
Ok mate....found a couple of parameters and have come up with this code:

********************************************************************************
<?php
error_reporting(E_ALL);

// starting word
$word = new COM("word.application") or die("Unable to instantiate Word");
echo "Loaded Word, version {$word->Version}\n";

//bring it to front
$word->Visible = true;

$word->ActivePrinter = "\\\\resources\\Resources";

//open an empty document
$word->Documents->Add();

//do some weird stuff
$word->Selection->TypeText("This is a test...");
$word->Documents[1]->SaveAs("D:\inetpub\wwwroot\school\pdf\output\document.doc");


$word->ActiveDocument->PrintOut();

//closing word
//$word->Quit();

//free the object
//$word = null;
?>
********************************************************************************

This opens word on the server and saves the document and sends it to print on the Resources network printer. This is the Postscript printer setup to generate the PS file.

It gets to the save screen and stops (logically) to ask for a filename and location. Is there any way I can automate this so I can tell Word where I want the file saving and what to call it?

Thanks,
MOZZER
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17152860
When you recorded the process, did you have to enter the details?

If they are NOT saved in the macro, then Word is NOT asking for them, but an external library.

Personally, I would NOT use word like this. Imagine 20 users all at the same time - 20 instances of word! EEEK!
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17152865
Let's try and get the GS working as I think this is the route you really want.
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17152980
Hey,

Ok back to GS - sorry just wanted to see if i could do it with COM.....worth a try :)

I have used the code you mentioned to output what is happening and this is what it printed:

******************************************************************************************************
Before : C:/Progra~1/gs/gs8.54/bin/gswin32c.exe -sDEVICE=pdfwrite -r300 -sOutputFile=C:\PHP\uploadtemp\phpEC5D.tmp.pdf -dNOPAUSE -dBATCH C:\PHP\uploadtemp\phpEC5D.tmp

After : C:\Progra~1\gs\gs8.54\bin\gswin32c.exe -sDEVICE=pdfwrite -r300 -sOutputFile=C:\PHP\uploadtemp\phpEC5D.tmp.pdf -dNOPAUSE -dBATCH C:\PHP\uploadtemp\phpEC5D.tmp

Results : array ( 0 => 'AFPL Ghostscript 8.54 (2006-05-17)', 1 => 'Copyright (C) 2005 artofcode LLC, Benicia, CA. All rights reserved.', 2 => 'This software comes with NO WARRANTY: see the file PUBLIC for details.', 3 => 'Loading NimbusMonL-Regu font from C:\\Program Files\\gs\\fonts/n022003l.pfb... 2573384 1100442 1915728 616670 1 done.', 4 => '%%[ ProductName: AFPL Ghostscript ]%%', 5 => '%%[Page: 1]%%', 6 => '%%[LastPage]%%', ) 0
******************************************************************************************************

I am presuming that the results showing "'AFPL Ghostscript 8.54 (2006-05-17)" means that it is at least connecting to the GS program?

Does this all look ok?
MOZZER
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17153005
Now run the "after" command at the command prompt.




0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 17153013
ARGH!! You dozy bugger.

You cannot access the tmp files as they are for PHP's use.

Use move_uploaded_file() to move the file from the temp are to somewhere else and use that file in the command_line.
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17153092
Hmmmm ok sort of a restult :)

I have managed to get the code working and its created the PDF file :)

Bad news? Its a 0 byte file and the submission page still times out. Here is the code:

***********************************************************************************************
<?php
// Turn on error reporting
error_reporting(E_ALL);

// Create a page with a message and abort the script (error reporting for the user)
function print_message($s)
      {die('<html><body><h1>Warning!</h1>'.$s.'</body></html>');}

// Check the file was uploaded
if(!count ($_FILES || $_FILES['infile']['error'] || strcmp($_FILES['infile']['type'], 'application/postscript')))
      {print_message('No file uploaded or ipload error!');}

// Set the location for the uploaded file
$uploadDir      = 'D:\inetpub\wwwroot\school\pdf\output\\';
$uploadFile      = $uploadDir.basename($_FILES['infile']['name']);

if(!move_uploaded_file($_FILES['infile']['tmp_name'], $uploadFile))
      {print_message('Unable to move temporary file!');}

// Try running the file through Ghostscript
exec('"C:\Program Files\gs\gs8.54\bin\gswin32c.exe" -sDEVICE=pdfwrite -r300 -sOutputFile='.$uploadFile.'.pdf -dNOPAUSE -dBATCH'.$uploadFile, $a, $n);

if($n)
      {print_message('Unable to convert file. Please ensure that you have used the proper format and try again.');}

// Output the headers to tell the browser what type of file is being outputted, how long it is and how we want it displayed
header('Content-Type: application/pdf');
header('Content-Disposition: filename="'.$_FILES['infile']['name'].'.pdf%20"');
header('Content-Length: '.filesize($_FILES['infile']['tmp_name'].'.pdf'));

// Dump the PDF file and delete it from the PHP folder
readfile($_FILES['infile']['tmp_name'].'pdf');
unlink($_FILES['infile']['tmp_name'].'pdf');
?>
***********************************************************************************************

It's as if it is either waiting for something or its crashed.....any ideas?

MOZZER
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17153110
Sorry forgot about the bottom $_FILES variables......have replaced them all with $uploadDir and it does exactly the same thing.

MOZ
0
 
LVL 40

Accepted Solution

by:
Richard Quadling earned 500 total points
ID: 17153182
....  -dBATCH'.$uploadFile, .....

No space between BATCH and the filename.
0
 
LVL 1

Author Comment

by:nikez2k4
ID: 17153202
God damn it....

Ok I am very embarassed to say that I have fixed the problem....it was a spacing problem - however I am going to blame it on the guide i followed as it doesnt clearly show a space lol.....

Here is the final code to create a PDF from a PostScript file:

****************************************************************************************
<?php
// Turn on error reporting
error_reporting(E_ALL);

// Create a page with a message and abort the script (error reporting for the user)
function print_message($s)
      {die('<html><body><h1>Warning!</h1>'.$s.'</body></html>');}

// Check the file was uploaded
if(!count ($_FILES || $_FILES['infile']['error'] || strcmp($_FILES['infile']['type'], 'application/postscript')))
      {print_message('No file uploaded or ipload error!');}

// Set the location for the uploaded file
$uploadDir      = 'D:\inetpub\wwwroot\school\pdf\output\\';
$uploadFile      = $uploadDir.basename($_FILES['infile']['name']);

if(!move_uploaded_file($_FILES['infile']['tmp_name'], $uploadFile))
      {print_message('Unable to move temporary file!');}

// Try running the file through Ghostscript
exec('"C:\Program Files\gs\gs8.54\bin\gswin32c.exe" -sDEVICE=pdfwrite -r300 -sOutputFile='.$uploadFile.'.pdf -dNOPAUSE -dBATCH '.$uploadFile, $a, $n);

if($n)
      {print_message('Unable to convert file. Please ensure that you have used the proper format and try again.');}

// Comment out the lines below if you want the PDF file to be saved, otherwise it will display the PDF in the browser

// Output the headers to tell the browser what type of file is being outputted, how long it is and how we want it displayed
header('Content-Type: application/pdf');
header('Content-Disposition: filename="'.$uploadFile.'.pdf%20"');
header('Content-Length: '.filesize($uploadFile.'.pdf'));

// Dump the PDF file and delete it from the PHP folder
readfile($uploadFile.'.pdf');
unlink($uploadFile.'.pdf');
?>
****************************************************************************************

Cheers for helpin mate!
MOZZER
0

Featured Post

Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In a previous article here at Experts Exchange (http://www.experts-exchange.com/articles/18414/Create-a-PDF-file-with-Contact-Sheets-montage-of-thumbnails-for-all-JPG-files-in-a-folder-and-each-of-its-subfolders-using-an-automated-batch-method.html)…
Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
This video Micro Tutorial is the first in a two-part series that shows how to create and use custom scanning profiles in Nuance's PaperPort 14.5 (http://www.experts-exchange.com/articles/17490/). But the ability to create custom scanning profiles al…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question