Solved

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

Posted on 2006-07-18
19
711 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
  • 10
  • 9
19 Comments
 
LVL 1

Author Comment

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

MOZ
0
 
LVL 40

Expert Comment

by:RQuadling
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
 
LVL 40

Expert Comment

by:RQuadling
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:RQuadling
ID: 17152610
Can you replace

exec( ..... );

with

echo ...;

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

Expert Comment

by:RQuadling
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:RQuadling
ID: 17152819
// Print it
$word->PrintOut();

All the parameters are defaulted and this works on my version 11.0
0
Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

 
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:RQuadling
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:RQuadling
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:RQuadling
ID: 17153005
Now run the "after" command at the command prompt.




0
 
LVL 40

Expert Comment

by:RQuadling
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:
RQuadling 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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Microsoft Office Picture Manager is not included in Office 2013. This comes as a shock to users upgrading from earlier versions of Office, such as 2007 and 2010, where Picture Manager was included as a standard application. This article explains how…
This article discusses four methods for overlaying images in a container on a web page
Microsoft Office Picture Manager has a Picture Shortcuts pane that shows a list with the Recently Browsed folders. While creating my video Micro Tutorial here at Experts Exchange showing How to Install Microsoft Office Picture Manager in Office 2013…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

895 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now