Solved

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

Posted on 2006-07-18
19
707 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
Comment Utility
Any ideas guys???

MOZ
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
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
Comment Utility
Ahh i get ya - hold on i'll try that now :)

MOZ
0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
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
Comment Utility
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
Comment Utility
Can you replace

exec( ..... );

with

echo ...;

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

Expert Comment

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

All the parameters are defaulted and this works on my version 11.0
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 1

Author Comment

by:nikez2k4
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Now run the "after" command at the command prompt.




0
 
LVL 40

Expert Comment

by:RQuadling
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
....  -dBATCH'.$uploadFile, .....

No space between BATCH and the filename.
0
 
LVL 1

Author Comment

by:nikez2k4
Comment Utility
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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Jump links not quite lining up 18 48
get radio button vale in array 7 33
PHP Sum Column in Table 3 25
Not needed 13 52
I. Introduction In a previous article (http://www.experts-exchange.com/Web_Development/Document_Imaging/A_6537-PaperPort-Upgrade-How-to-download-and-install-updated-versions-of-PaperPort-11-and-12.html) (now deprecated), I discussed how to upgrad…
PaperPort has a feature called the "Send To Bar". It provides a convenient, drag-and-drop interface for using other installed software, such as Microsoft Office. However, this article shows that the latest Office 2016 apps (installed with an Office …
In this video, we show how to convert an image-only PDF file into a PDF Searchable Image file, that is, a file with both the image (typically from scanning) and text, which is created in an automated fashion with Optical Character Recognition (OCR) …
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…

762 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

7 Experts available now in Live!

Get 1:1 Help Now