PHP - send file to user

Php

Php Problem Overview


I have a pdf file on disk that i need to send to a user when they make a request to a php script, what is the best way of doing this?

Php Solutions


Solution 1 - Php

Assuming that it's on the server:

> readfile() — Outputs a file

NOTE: Just writing

readfile($file);

won't work. This will make the client wait for a response forever. You need to define headers so that it works the intended way. See this example from the official PHP manual:

<?php
$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename='.basename($file));
    header('Content-Transfer-Encoding: binary');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    ob_clean();
    flush();
    readfile($file);
    exit;
}
?>

Solution 2 - Php

Here is what you need to send a file with PHP :

$filename = "whatever.jpg";

if(file_exists($filename)){

    //Get file type and set it as Content Type
	$finfo = finfo_open(FILEINFO_MIME_TYPE);
	header('Content-Type: ' . finfo_file($finfo, $filename));
	finfo_close($finfo);

    //Use Content-Disposition: attachment to specify the filename
    header('Content-Disposition: attachment; filename='.basename($filename));

    //No cache
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');

    //Define file size
    header('Content-Length: ' . filesize($filename));

    ob_clean();
    flush();
    readfile($filename);
    exit;
}

As Julian Reschke commented, the validated answer MAY work, but it's full of useless headers. The content-type should be set to the real type of the file, or some browsers (especially mobile browsers) may not download it properly.

Solution 3 - Php

If you are using Apache or Lighty, then the "best" way to do this from a performance point of view, is to use the X-Sendfile header. See this tutorial: https://www.h3xed.com/programming/how-to-use-x-sendfile-with-php-apache

Solution 4 - Php

Ok, so I’m no expert at PHP, I can only take credit for putting together a few other snippets of PHP to achieve what i needed it to do, and i thought i had better post this solution up in a few forums which asked the same question but i could not get to work myself. There did not seem to be a solution anywhere so here it is. It works for me... Ok so first off i created the PDF form and added a button which then submits form. In the actions of this submit form, i told it to PDF the complete document. Then i gave it a URL link to a php page, such as mail_my_form.php Then i created a php form, and named it the same as above... mail_my_form.php One last thing is to create a folder called pdfs in the root of where this php code will go. (So if you put the php in a folder called email, then inside the folder of email, you need another folder called pdfs) Now what this script does is: Saves the PDF to the file name pdfs. Then it attaches the file to an email and sends it. Then it deletes the file from the folder pdfs to save space. (you could take out the delete function to save your forms on your FTP also if you wanted to.
Here it is.

<?php 
$fileatt = date("d-m-Y-His") . ".pdf";  // Creates unique PDF name from the date 
copy('php://input',"pdfs/".$fileatt); // Copies the pdf form data to a folder named pdfs 
$fileatt = "pdfs/".$fileatt; // Path to the file gives the pdfs folder plus the unique file name we just assigned
$fileatt_type = "application/pdf"; // File Type 
$fileatt_name = "Application Form_".$fileatt.".pdf"; // Filename that will be used for the file as the attachment when it is sent

$email_from = "mywebsite"; // Who the email is from 
$email_subject = "Completed online Applications"; // The Subject of the email 
$email_message = "Please find a recent online application attached.
";
 $email_message .= "Any problems please email me...
"; // Message that the email has in it 

$email_to = "[email protected]"; // Who the email is to 

$headers = "From: ".$email_from;

//no need to change anything else under this point

$file = fopen($fileatt,'rb'); 
$data = fread($file,filesize($fileatt)); 
fclose($file); 

$semi_rand = md5(time()); 
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; 

$headers .= "\nMIME-Version: 1.0\n" . 
"Content-Type: multipart/mixed;\n" . 
" boundary=\"{$mime_boundary}\""; 

$email_message .= "This is a multi-part message in MIME format.\n\n" . 
"--{$mime_boundary}\n" . 
"Content-Type:text/html; charset=\"iso-8859-1\"\n" . 
"Content-Transfer-Encoding: 7bit\n\n" . 
$email_message .= "\n\n"; 

$data = chunk_split(base64_encode($data)); 

$email_message .= "--{$mime_boundary}\n" . 
"Content-Type: {$fileatt_type};\n" . 
" name=\"{$fileatt_name}\"\n" . 
//"Content-Disposition: attachment;\n" . 
//" filename=\"{$fileatt_name}\"\n" . 
"Content-Transfer-Encoding: base64\n\n" . 
$data .= "\n\n" . 
"--{$mime_boundary}--\n"; 

$ok = @mail($email_to, $email_subject, $email_message, $headers); 

if($ok) { 
unlink($fileatt); //NOW WE DELETE THE FILE FROM THE FOLDER pdfs 
Header("Location: nextpage.php"); //where do we go once the form has been submitted.
 
} else { 
die("Sorry but the email could not be sent. Please go back and try again!"); 
} 
?>

Hope this helps some of you.

Richard Williams

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIan morganView Question on Stackoverflow
Solution 1 - PhpAdiraelView Answer on Stackoverflow
Solution 2 - PhpRayjaxView Answer on Stackoverflow
Solution 3 - PhpchiborgView Answer on Stackoverflow
Solution 4 - PhpRichardView Answer on Stackoverflow