ian morgan
Tengo un archivo pdf en el disco que necesito enviar a un usuario cuando realiza una solicitud a un script php, ¿cuál es la mejor manera de hacerlo?
Adirael
Suponiendo que está en el servidor:
readfile() — Muestra un archivo
NOTA: solo escribiendo
readfile($file);
no funcionará Esto hará que el cliente espere una respuesta para siempre. Debe definir encabezados para que funcione de la manera prevista. Vea este ejemplo del manual oficial de PHP:
<?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;
}
?>
-
Funciona para mí bajo IE8/Vista. ¿Te da error o simplemente carga una página en blanco?
– Adirael
21 de mayo de 2010 a las 14:29
-
El ejemplo contiene mucha basura. Content-Description no existe en HTTP. Content-Type debe establecerse en el tipo de medio real, o ninguno en absoluto. El código para Content-Disposition producirá encabezados incorrectos para muchos nombres de archivo. La codificación de transferencia de contenido no existe en HTTP. Ver también blogs.msdn.com/b/ieinternals/archive/2012/05/16/… con respecto a Cache-Control.
– Julián Reschke
20 de mayo de 2012 a las 7:42
-
@Julian Reschke: ¿Y por qué está oficialmente en php.net?
– Tim
23 de abril de 2014 a las 9:32
-
Siento que esta respuesta podría ayudar a las personas que no están seguras de los encabezados.
– Dominó
23 de abril de 2015 a las 13:10
-
encontré esta entrada de blog (y guión complementario (con algunas mejoras de ‘Hargobind’)) por Armand Niculescu muy útil. Ambos enlaces tienen múltiples copias en archive.org por cierto.
– GitaarLAB
23 de julio de 2015 a las 1:46
Rayjax
Esto es lo que necesita para enviar un archivo con 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;
}
Como comentó Julian Reschke, la respuesta validada PUEDE funcionar, pero está llena de encabezados inútiles. El tipo de contenido debe establecerse en el tipo real del archivo, o algunos navegadores (especialmente los navegadores móviles) pueden no descargarlo correctamente.
-
Gracias, especialmente por
ob_clean(); flush();
– Fantasma
26 de septiembre de 2017 a las 6:43
-
¿podría agregar comentarios a la
ob_clean
yflush
pedacitos? ¿Qué problemas potenciales resuelven?– YakovL
20 de enero de 2018 a las 10:12
-
Content-Disposition requiere ” ” alrededor del nombre del archivo en caso de que tenga espacios
– anónimo
6 de mayo de 2018 a las 2:04
-
funcionó como un encanto para mí, gracias
– DarkCygnus
12 abr 2022 a las 21:38
Chiborg
Si está usando Apache o Lighty, entonces la “mejor” manera de hacerlo desde el punto de vista del rendimiento es usar el X-Sendfile
encabezamiento. Ver este tutorial: https://www.h3xed.com/programming/how-to-use-x-sendfile-with-php-apache
-
El enlace está roto. Aquí hay una alternativa: h3xed.com/programming/how-to-use-x-sendfile-with-php-apache
– DannyB
11 de junio de 2020 a las 14:14
Ok, no soy un experto en PHP, solo puedo atribuirme el mérito de reunir algunos otros fragmentos de PHP para lograr lo que necesitaba que hiciera, y pensé que sería mejor publicar esta solución en algunos foros que preguntaron la misma pregunta pero no pude ir a trabajar yo mismo. No parecía haber una solución en ninguna parte, así que aquí está. Funciona para mí … Ok, primero creé el formulario PDF y agregué un botón que luego envía el formulario. En las acciones de este formulario de envío, le dije a PDF el documento completo. Luego le di un enlace URL a una página php, como mail_my_form.php Luego creé un formulario php y lo nombré igual que arriba… mail_my_form.php Una última cosa es crear una carpeta llamada pdfs en la raíz de dónde irá este código php. (Entonces, si coloca el php en una carpeta llamada correo electrónico, luego dentro de la carpeta de correo electrónico, necesita otra carpeta llamada pdfs) Ahora lo que hace este script es: Guarda el PDF con el nombre de archivo pdfs. Luego adjunta el archivo a un correo electrónico y lo envía. Luego elimina el archivo de la carpeta pdfs para ahorrar espacio. (También puede eliminar la función de eliminación para guardar sus formularios en su FTP si lo desea.
Aquí lo tienes.
<?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 = "youremail@yourserver.com"; // 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!");
}
?>
Espero que esto ayude a alguno de ustedes.
ricardo williams