Link to home
Start Free TrialLog in
Avatar of nejizofa
nejizofa

asked on

How do I save a pdf file open in a browser window back to the server

Ok, here's what I'm trying to do:

I have a pdf file named Test.pdf
I open it in a browser window (works fine)
The pdf has a submit (save) button that posts the entire pdf back to the same url with a querystring added (save)
I am trying to save the file back to the server and overwrite the original.

The part I am having a problem with is getting it to save the file overwriting the original
<?php
if (isset($_POST['filename']))
{
	$pdf = $_POST['filename'];
	header('Content-Description: Display PDF');
    header('Pragma: public');
    header('Content-Length: ' . filesize($pdf));
	header("Cache-control: private");
	header("Content-Type: application/pdf");
filename=temp_".$_POST['ckbox'].".pdf");
	ob_clean();
    flush();
    readfile($pdf);
}
else echo "incorrect submission";
 
if (isset($_GET['save']))
{
	
	$fn = $_POST['filename']; //original filename
	copy('php://input', $fn);
	echo "File successfully saved, you may now close this window";
}
 
?>

Open in new window

Avatar of Michael701
Michael701
Flag of United States of America image

first this line needs help
filename=temp_".$_POST['ckbox'].".pdf");
should be
$filename="temp_".$_POST['ckbox'].".pdf");

next are you sure this
if (isset($_GET['save']))
shouldn't be
if (isset($_POST['save']))
I find it odd that a post submit would set the $_GET
Question for you. Is this a pdf where the user fills out a form and submits the completed form back to your server? If so, are the fields available in PHP? I'd like to see a sample of this working.
Avatar of nejizofa
nejizofa

ASKER

I have corrected the code snippet.
Let me clarify a little.
The post variable "filename" gets the file location on the server
I open it on the page using header and readfile
This much works fine
Second step--
On the pdf is a save button that sends the updated pdf back to the url
As far as I understand it, it is not a POST. it simply streams the file in.
This is why I am trying to catch it with "copy('php://input', $fn);"
the "copy('php://'" seems to work to grab the incoming file, but I don't know how to save it back to its original location and name because there are no POST variables after the round-trip from the pdf.
I attempted to use a GET by setting the url on the pdf save button (i.e. ...processpdf.php?save=1)
This satisfied the second if condition...

The last bit I need to figure out is how to maintain the filename so I can save it off properly.
Sorry if this is confusing.
<?php
if (isset($_POST['filename']))//display the pdf file in post variable
{
 
	$pdf = $_POST['filename'];
	header('Content-Description: Display PDF');
        header('Pragma: public');
        header('Content-Length: ' . filesize($pdf));
	header("Cache-control: private");
	header("Content-Type: application/pdf");
	ob_clean();
        flush();
        readfile($pdf);
}
 
//this is where I check for the round trip from the pdf save button
if (isset($_GET['save']))
{
	
	$fn = //this is what I can't figure out how to get, it needs to be the same filename that is posted originally from above
	copy('php://input', $fn);
	
}
 
?>

Open in new window

ah, take a look at this. I think it's what you're attempting to do.

http://koivi.com/fill-pdf-form-fields/tutorial.php
Yes, the user fills out the pdf fields and sends it back to the server.
On the pdf button preferences, you can submit it several ways.
FDF
HTML
XFDF
PDF

If I use the FDF or XFDF functionality, I do have access to all the fields, but the formatting,text,images are lost. I can reload them back into the original pdf but that isn't necessary for my situation.
The PDF functionality seems to fit my needs, I just need to overwrite the original file with the new one.
Michael,
Thanks for your help on this. I have read the tutorial that you posted.
My only problem with doing it that way is that the pdf form's I need to save have from 200-600 fields, checkboxes, etc. I also have at least 50 PDF's that I need to support, and they change frequently. It would be extremely hard to keep track of all those docs and fields... I don't need to know what info was changed, I just need to overwrite the old file with the new one.

It seems so close, displaying and saving the file works. Maintaining and Overwriting the correct file is the problem. Any thoughts?
can you see if $_FILES is set upon the return of the data?

print_r ($_FILES); // as it should be an array

what I don't get from your example is that it may take minutes or hours for someone to complete the pdf form and press submit. I can't see the php script being active for that amount of time.

I'm hoping to see that the data is sent back just as someone would upload an image (or any file) from an html form. Then you can use the standard file upload code
http://us2.php.net/manual/en/features.file-upload.post-method.php
I checked and $_FILES is not set
The only way I could find to get the incoming file was by using "copy('php://input', $fn);"

in fact, here is a dump of everything

array(30) { ["CONTENT_LENGTH"]=> string(6) "308800" ["CONTENT_TYPE"]=> string(15) "application/pdf"
["DOCUMENT_ROOT"]=> string(37) "/home//public_html/" ["GATEWAY_INTERFACE"]=>
string(7) "CGI/1.1" ["HTTP_ACCEPT"]=> string(165) "application/vnd.fdf, application/vnd.adobe.xfdf,
application/vnd.adobe.xdp+xml, text/html, text/plain, image/gif, image/jpeg, image/png, image/x-png, application/pdf"
["HTTP_ACROBAT_VERSION"]=> string(5) "9.0.0" ["HTTP_AUTHORIZATION"]=> string(0) ""
["HTTP_CONNECTION"]=> string(10) "keep-alive" ["HTTP_HOST"]=> string(18) "www.domain.com"
["HTTP_USER_AGENT"]=> string(114) "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en-US) AppleWebKit/523.15
(KHTML, like Gecko) Version/3.0 Safari/523.15" ["PATH"]=> string(13) "/bin:/usr/bin" ["QUERY_STRING"]=>
string(10) "compid=100" ["REDIRECT_STATUS"]=> string(3) "200" ["REMOTE_ADDR"]=> string(12)
"234.15.46.85" ["REMOTE_PORT"]=> string(5) "34185" ["REQUEST_METHOD"]=> string(4) "POST"
["REQUEST_URI"]=> string(32) "/process_pdf.php?compid=100" ["SCRIPT_FILENAME"]=> string(58)
"/process_pdf.php" ["SCRIPT_NAME"]=> string(21)
"/process_pdf.php" ["SERVER_ADDR"]=> string(14) "74.345.345.157" ["SERVER_ADMIN"]=> string(36)
"webmaster" ["SERVER_NAME"]=> string(18) "www.domain.com"
["SERVER_PORT"]=> string(2) "80" ["SERVER_PROTOCOL"]=> string(8) "HTTP/1.1"
["SERVER_SIGNATURE"]=> string(177) "
Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8i DAV/2 mod_auth_passthrough/2.1 mod_bwlimited/1.4
FrontPage/5.0.2.2635 Server at www.domain.com Port 80
" ["SERVER_SOFTWARE"]=> string(120) "Apache/2.2.11 (Unix) mod_ssl/2.2.11 OpenSSL/0.9.8i DAV/2
mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635" ["PHP_SELF"]=> string(21)
"/docs/process_pdf.php" ["REQUEST_TIME"]=> int(1234228140) ["argv"]=> array(1) { [0]=> string(10)
"compid=100" } ["argc"]=> int(1) } Array ( )
the "copy('php://input', $fn);" works and successfully saves the pdf. I just can't figure out how to tell it where to save and what file name because it needs to overwrite the original one.
well wouldn't $fn be the file name? try hard coding the name

copy('php://input', '/my_file.pdf');

or maybe the post variable is still available

copy('php://input',$_POST['filename']);
The POST isn't there.
If I hard code the name, it works like a charm. The problem is that I need to name the file based on which one they're editing.

For example, if they open /docs/test1.pdf - I pass that in the original post and it opens.
I just need to maintain somehow that test1.pdf is the one that is open for when the stream comes back when they save by hitting the pdf button.
I tried setting a cookie and a session variable with the name, but for some reason none of those work. I think it has something to do with how the adobe reader plugin sends the file back.

If I hard code it, someone could open /docs/test2.pdf and it would overwrite test1.pdf
Its crazy, seems like it would be a quick thing.
ASKER CERTIFIED SOLUTION
Avatar of Michael701
Michael701
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The remote address idea is a good idea for sure. I'll try it and see if it works.
Yes, I did set the cookie before the header info. Should I have set it afterwards?
No you should set the cookie first
OK, The remote Address method works to an extent. I basically created a table in mysql one column for the filename, the other for the remote address.
When the user clicks the button to open the pdf, I store the file name and the remote address off.
When it comes back, it checks their remote address and automatically saves the incoming file to the location associated with it in the db.

There are a couple of problems with this solution though.
1- they can only have one file out at a time, 2 or more makes the solution overwrite the same file even if its not the right one.

2- I just learned that only Adobe acrobat pro supports posting the entire file back, so they can't do it with adobe reader.

Sooo.  I basically need to find another way to open a pdf file in the browser, let the user edit it, and then save it back to the server.

Any other thoughts on how to do this?
bummer, and this was sounding like a good idea.
does abode reader allow the field to be submitted back to the server?

sounds like you might have to look at using php to create a new pdf based on the fields they changed.

do a phpinfo() and see if the pdf library stuff is installed.
PDFlib isn't installed, its on hostmonster so I can't change that either.
I experimented with using FDPF but it doesn't have support for reading in an existing document and I can't recreate them with it either because of the number of fields and drop downs, etc.

Thanks again!