For an insurance company, I've created PDF forms of their various insurance applications. These will be available on their website (when it is done). Each form, being in PDF, looks exactly like the printed version of the application. The idea is that a user fills it out online, hits the (visible but unprintable) "Submit" button at the bottom of the form, and the entire completed PDF is sent to the company. That way they can print it out, and carry on with their current paper filing system.
I experimented with using a "mailto:..." URL for the Submit button, but that requires an external mail program. It also gives the attached PDF a random temp filename.
Therefore, I'd like to send the PDF to a php script, change the name, and email it to the company from there. I played with it a bit, and I can reach the destination script, but I have no idea what happens to the PDF. I expected it to show up in $_FILES, but nothing.
Saving to a database is not an option.
When preparing the PDF form, you can choose how you would like to submit: as an HTML form (as Sepodati said), as XML data, as FDF (which only sends data, and will open the original PDF when displaying the data), or as a completed PDF. For ease of use for the site owners, who are not computer savvy, I'm going to send them a completed PDF that they can print.
So, the same question remains: where does my PDF file go when I get to my destination script?
I'm submitting the PDF via a Submit button on the PDF itself. You'll have to be familiar with PDF forms to understand this. For the URL, I put the destination PHP script.
In my destination script, I tried the following
PHP Code:
reset ($_FILES);
while (list ($key, $val) = each ($_FILES)) {
echo "$key => $val<br />\n";
}
I did this for $_FILES, $_GET, $_POST, and $_REQUEST. Nothing came up, as though each array was empty. I might have done this wrong, though.
I put phpinfo() in the script, and these vars appear related to the PDF...
_SERVER["CONTENT_LENGTH"] = 37722
_SERVER["CONTENT_TYPE"] = application/pdf
_SERVER["HTTP_USER_AGENT"] = Mozilla/4.0 (compatible; Adobe Acrobat Control Version 5.00 for ActiveX)
_SERVER["REQUEST_METHOD"] = POST
The content length is approximately the size of the PDF.
Something else I didn't notice before is that upon submission, Internet Explorer displays this page (or a name like it):
C:\WINDOWS\TEMP\pa003773.html
This page contains all the output from my script.
It's very interesting that it's supposed to send the entire PDF. I would be interested in knowing how it does that because I've searched the Adobe site for information on how to submit an entire PDF file by clicking a button on the PDF form.
The only thing I found on their site was information about the FDF and XFDF formats. Both of these formats have to be parsed in some way by your form handler script and aren't included in $_FILES the way a file is uploaded when you select the file from the filesystem.
$fptr = fopen("temp.fdf", "w");
fputs($fptr, $HTTP_RAW_POST_DATA);
fclose($fptr);
This is a really old post so I'm sure you've gotten your answer by now but here's what worked for me in case anyone else stumbles across this in the future.
BTW- this only works for if you are submitting the entire PDF with the form fields completed.The address you would put on your submit button would be something like http://youserver.com/lib/php/formProcess.php?email=to#company.com&formName=Asset%20Inventory
<?php
ob_start();
$file = file_get_contents("php://input"); //Gets binary PDF Data
$time = microtime(true);
//Names pdf file based on the time to the microsecond so nothing gets overwritten. Obviously you can change this to whatever you want or do something like $_REQUEST['formName'] and just include the form name in your URL from your pdf submit button
$newfile = "forms/" . $time . ".pdf";
$worked = file_put_contents($newfile, $file); //Creates File
ob_end_clean();
//Upon completion you can either return XFDF to update a field on your form or display a PDF document. I chose the PDF route because it worked for our situation.
$successFile = 'success.pdf';
$errFileFile = 'error.pdf';
require 'PHPMailer/PHPMailerAutoload.php';
$mail = new PHPMailer;
$mail->isSendmail();
$mail->setFrom('From email address', 'from name');
$mail->addReplyTo('Reply to email', 'Reply to name');
$mail->addAddress($_REQUEST['email']); //get email from URL- alternately you can just hardcode in an address
$mail->addAttachment( $newfile );
$mail->isHTML(true);
$mail->Subject = 'New form submission';
$mail->Body = 'A new form has been submitted.';
if(!$mail->send()) {
header('Content-type: application/pdf');
readfile($errFile);
} else {
header('Content-type: application/pdf');
readfile($successFile);
//if you want to delete the file from the server after emailing: unlink($newfile);
}
?>
Related
I've been using the advice given in this question:
Merge FDF data into a PDF file using PHP
to determine how I can pre-populate a pdf form with data pulled from a database but not getting the data to file. I'm running php 5.3.15 on Mountain Lion and I'm using the following link to combine the pdf with the fdf on a table page that I'd like to allow the user to click and take them to a populated pdf file:
something.pdf#FDF=generatePdf.php
The generatePdf.php looks like this:
<?php
$pdf_form_url= "";
require_once('forge_fdf.php');
$fdf_data_names= array(); // none of these in this example
$fdf_data_strings= array(); // none of these in this example
$fdf_data_strings['form1[0].#subform[0].q1a_LastName'] = "Smith";
$fields_hidden= array();
$fields_readonly= array();
// set this to retry the previous state
$retry_b= false;
header( 'content-type: application/vnd.fdf' );
echo forge_fdf( $pdf_form_url,
$fdf_data_strings,
$fdf_data_names,
$fields_hidden,
$fields_readonly );
?>
and the FDF file looks like this when I run it through the pdftk command line:
FieldType: Text
FieldName: form1[0].#subform[0].q1a_LastName[0]
FieldNameAlt: Enter Family Name
FieldFlags: 0
FieldJustification: Left
FieldMaxLength: 35
Still, when I run it the form doesn't auto populate. I've tried many variations including just using the q1a_LastName by itself and I still end up with an empty form. The forge_fdf.php is in the same directory.
Update:
I've also attempted the conventional method outlined in the Merge FDF data into a PDF question that I've linked to using PHP, meaning I didn't just direct the user to a pdf file but also attmepted to have the user download the pdf. In that particular case, I would receive a message saying the pdf was empty. I've checked the created raw FDF file and it appears to be populating with data. In either case, I'm not getting what I need.
After much trial and error I realized that the best way to autopopulate to a url linking to a pdf is to define the $pdf_form_url variable for the code above. This code will echo out the details of the fdf file. If you explicitly specify what the pdf url is, php and your browser will take the necessary steps to link you to a the pdf in your web browser with the embedded field information coming from the fdf output.
So I stumbled upon this thread and couldn't get it to work even when I populate the $pdf_form_url variable. Here's my code:
require_once('forge_fdf.php');
// leave this blank if we're associating the FDF w/ the PDF via URL
$pdf_form_url= "http://test.pdf";
// $pdf_form_url= "";
// default data; these two arrays must ultimately list all of the fields
// you desire to alter, even if you just want to set the 'hidden' flag;
//
//
$fdf_data_names= array(); // none of these in this example
$fdf_data_strings= array(); // none of these in this example
$fdf_data_strings['Address, Row 1']="XXXX Balboa Arms Drive #XXX, San Diego CA 01234";
$fields_hidden= array();
$fields_readonly= array();
// set this to retry the previous state
$retry_b= false;
header( 'content-type: application/vnd.fdf' );
echo forge_fdf( $pdf_form_url,
$fdf_data_strings,
$fdf_data_names,
$fields_hidden,
$fields_readonly );
And here's the form field I want to update using pdftk dump_data_fields:
FieldType: Text
FieldName: Address, Row 1
FieldNameAlt: (Address, <Row 1>)
FieldFlags: 0
FieldJustification: Center
Im making a website for a band, and they are giving out their EP for free, but they want it so the user has to enter their email address before downloading... How would this be done in php?
The downloadable should be placed out of the reach of web user but within your PHP script reach. Then once user is done filling form, you can then force download the file contents by opening it locally using say "fopen".
Update (Adding Sample Code):
Suppose the file is "txt.txt" which could be in your script reach. You will open it, read and then put the contents after calling header and telling it that its an attachment (force download)
$done = true;
if($done == true){
$filename = "txt.txt";
$conn = fopen($filename,"r");
$contents = fread($conn, filesize($filename));
fclose($conn);
header('Content-type: text/plain');
header('Content-Disposition: attachment; filename="downloaded.txt"');
echo $contents;
}
If you're storing the emails somehow, then simply set a $_SESSION value when they submit their email, and when writing the page, if the part of the $_SESSION value has been set, then provide a link to the media.
To start a session & set the value:
session_start();
$_SERVER['hasEmail']=true;
And in the page:
session_start();
if ($_SERVER['hasEmail']) {
//Provide link
}
You could then also have the media link take you to a PHP script which uses fopen() or similar to get the file from another location on your filesystem out of reach of the user, such as one under .htaccess blocking, and it'll only provide the media is the $_SESSION value is set.
I've got a large form where the user is allowed to input many different fields, and when they're done I need to send the contents of the form to the server, process it, and then spit out a .txt file containing the results of the processing for them to download. Now, I'm all set except for the download part. Setting the headers on the response to the jQuery .post() doesn't seem to work. Is there any other way than doing some sort of iframe trick to make this work (a la JavaScript/jQuery to download file via POST with JSON data)?
Again, I'm sending data to the server, processing it, and then would like to just echo out the result with headers to prompt a download dialog. I don't want to write the result to disk, offer that for download, and then delete the file from the server.
Don't use AJAX. There is no cross-browser way to force the browser to show a save-as dialog in JavaScript for some arbitrary blob of data received from the server via AJAX. If you want the browser to interpret the results of a HTTP POST request (in this case, offering a download dialog) then don't issue the request via AJAX.
If you need to perform some kind of validation via AJAX, you'll have to do a two step process where your validation occurs via AJAX, and then the download is started by redirecting the browser to the URL where the .txt file can be found.
Found this thread while struggling with similar issue. Here's the workaround I ended up using:
$.post('genFile.php', {data : data}, function(url) {
$("body").append("<iframe src='download.php?url="+url+"' style='display: none;'></iframe>");
});
genFile.php creates the file in staging location using a randomly generated string for filename.
download.php reads the generated file, sets the MIME type and disposition (allowing to prompt using a predefined name instead of the random string in the actual filename), returns the file content and cleans up by deleting the source file.
[edit] might as well share the PHP code...
download.php:
<?php
$fname = "/tmp/".$_GET['url'];
header('Content-Type: text/xml');
header('Content-Disposition: attachment; filename="plan.xml"');
echo file_get_contents($fname);
unlink ($fname);
?>
genFile.php:
<?php
$length = 12;
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = substr( str_shuffle( $chars ), 0, $length ).'.xml';
$fh = fopen(('tmp/'.$str), 'w') or die("can't open file");
fwrite($fh,$_POST["data"]);
fclose($fh);
echo $str;
?>
Rather than using jQuery's .post(), you should just do a normal POST by submitting the form, and have the server respond with appropriate Content-Encoding and MIME-type headers. You can't trigger a download through post() because jQuery encapsulates the returned data.
One thing I see in use rather frequently, though, is this:
$.post('generateFile.php', function(data) {
// generateFile builds data and stores it in a
// temporary location on the server, and returns
// the URL to the requester.
// For example, http://mysite.com/getFile.php?id=12345
// Open a new window to the returned URL which
// should prompt a download, assuming the server
// is sending the correct headers:
window.open(data);
});
Basic Idea: I have a flash file that takes screenshots with a click of a button, sending the data to a PHP file, and then the user gets to save a PNG image. The images that are merged together (via PHP) require that they reside on the same server as the PHP, otherwise they do not merge and the final PNG shows up blank.
My solution so far: I have two PHP files, and I just need to find a way to merge them. The screenshot one, and one that copies a file from one server to another. This is my cheat work around to bring the image to reside on the same server, THEN run the screenshot php.
The Server-to-Server PHP Code:
<?PHP
$inputfile = FOPEN("https://www.google.com/intl/en_com/images/srpr/logo3w.png", "r");
$outputfile = FOPEN("transferedfile.gif", "w");
ECHO "File opened...";
$data = '';
WHILE (!FEOF($inputfile)) {
$data .= FREAD($inputfile, 8192);
}
ECHO "Data read...";
FWRITE($outputfile, $data);
ECHO "transfered data";
FCLOSE ($inputfile);
FCLOSE ($outputfile);
ECHO "Done.";
?>
So as you can see, it pulls Google's logo and saves it as "transferedfile.gif" to the directory the PHP resides on. I can get this PHP code to work by saving this as whateverIWant.php on my webserver, and visiting it directly, but I need to in place of Google's logo (in this example) put a value that will be dynamically changing via flash.
So basically… in the flash file, I'll have a dyniamic variable where the URL will change, in short. So we'll just say that I define that variable in flash as var imageToGet so somehow I need to pass that variable into this PHP. That's one step... here's the AS 2.0 code:
My Actionscript (2.0) Code:
button.onRelease = function ():Void {
sendImageToServer();
ScreenShot.save(_root, "screenshot.png", 0, 0, 100, 140);
};
the sendImageToServer() function isn't made yet. This is where I'm stuck. I would need the sendImageToServer() function to send var imageToGet as what image to get, THEN run the ScreenShot.save() function after the transfer is done (aka FCLOSE ($outputfile); is complete)
In Summary: A movie clip on the stage will have a dynamic image loaded into it, that once a button is pressed, it would need to copy that dynamic image to the local server, and then run the screenShot function. I believe once I have this figured out, I should be able to do everything else, such as saving as a unique name, saving multiple files, etc. But I just need pushed in the right direction :)
Thanks so much everyone # StackOverflow. You've been nothing but awesome to me thus far!
EDIT -- I've found a good starting point!!
I found a good starting point, and am answering my own question in case someone else stumbles upon this. I used these two codes as a starting point, and I think I'm on the right track…
In Flash: I simply made a dynamic textbox with the instance name of traceText
In Actionscript (2.0):
var send:LoadVars = new LoadVars;
var receive:LoadVars = new LoadVars;
send.toPHP = "asd123";
receive.onLoad = function(){
encrypted = this.toFlash;
traceText.text = encrypted;
}
send.sendAndLoad("test.php",receive,"POST");
In "test.php" file:
$fromFlash = $_POST['toPHP'];
$encrypted = $fromFlash;
$toFlash = "&toFlash=";
$toFlash .= $encrypted;
echo $toFlash;
What this ended up doing was sending the variable to PHP and then back again. Which is perfect for what I needed. For now, I should be good! Hope this helps anyone that needs it.
Problem After downloading a CSV once, the form does not send a request on submission.
Purpose: To download a CSV file of information after choosing a few criteria for the download.
PHP Scripts:
export.php displays a HTML Form allowing the user to select certain criteria (which basically sets a couple of variables and then submitting those criteria in order to download the CSV file.
exportEntrants.php uses those variables set by the form to retrieve the appropriate data from the database, create the CSV data and then provide it as a download to the user.
So in export.php we have the following snippet:
require_once 'exportEntrants.php';
if(/*the form is submitted*/){
export($criteria);
}
else{
// Display the HTML Form
}
Which successfully calls the exportEntrants.php script when the form is submitted the first time.
Then in exportEntrants.php the data is created correctly and downloaded using:
function download($content,$title) {
header('Content-Description: File Transfer');
header("Content-type: application/csv");
header('Content-Disposition: attachment; filename="'.$title.'.csv";');
echo $content;
exit();
}
After which, the download works fine, and the CSV is correct. However on-screen the form is still visible to the user, so clicking the Submit button once more should trigger the if statement described above and allow me to download the file again with the same or different criteria as I see fit.
This doesn't happen though, nothing happens. The form is still displayed on screen, nothing has changed on screen at all, but submitting the form does not reload the page or cause any action.
Can anyone see what could be causing this problem? I will provide any additional information as needed.
Thank you.
EDIT in response to Comment from Hakre below.
Disabling Javascript made no difference.
This issue has been tested in Firefox 7.0.1 and Chrome 14. I have not yet tried IE or Safari.
The HTML of the form is as follows (I haven't included the criteria parts of the form as they work fine and the form is generated by a rather complicated function so it's not a small piece of HTML (lots of divs and spans):
<form action="/admin/export/export.php" method="post" name="exportForm" onsubmit="return formSubmit()"><input type="submit" name="submit_butt" value="EXPORT" class="button"></form>
The fact that the request is not being sent, when you press button repeatedly, seems to indicate an issue in client side. Check the formSubmit() function or page source of the client-side and see if maybe the attachment download somehow messed up Javascript.
#Tom Houdmont as I understand your question:
The file download scripts generally based on header function.
Using header() function has a condition that you can only send header information and can not echo or can not send any kind of text(space too) before or after it. Otherwise it will show you the warning: that header() information is already sent
Based on your code i tried one example:
In your case form action and download script, both are on same page so when your form is post check that any kind (even a space) data is printed before header() starts i.e or tag, or space. or you should cover whole ... in PHP if else statement.
I have uploaded simple image download script. here is link. You can download and run.
http://code.google.com/p/mixexperiments/downloads/detail?name=imagedownload.rar&can=2&q=
if still you dont get it, make me more clear, I will try my best
The problem you describe in your question is not related to the code you've posted.
I'm unable to reproduce your problem:
<?php
if ($_POST)
{
$title = 'test';
$content = 'Example file.';
header('Content-Description: File Transfer');
header("Content-type: plain/text");
header('Content-Disposition: attachment; filename="'.$title.'.txt";');
echo $content;
exit();
}
?>
<form method="post" action=""><input type="submit" name="submit" value="download"></form>
Test for yourself. Hope this helps to clarify where not your error is at least.