PHP: Sirva un archivo para descargar sin proporcionar el enlace directo

12

Quiero servir facturas para descargar. Actualmente estoy usando un esquema de numeración simple (factura-01.pdf, factura-02.pdf, etc.). Sé que podría usar hashes para ocultar los datos.

¿También es posible usar PHP y servir las facturas al no hacer que el usuario las señale directamente?

Frank Vilea
fuente
Si. ¿Qué tal " invoices.invalid / ... "?
mailq

Respuestas:

26

Incluso hay un ejemplo de esto en php.net

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?> 

O ampliar eso un poco con

<?php
if ( can_this_file_be_downloaded() ) {
  header('Content-type: application/pdf');
  header('Content-Disposition: attachment; filename="invoice.pdf"');
  readfile("{$_GET['filename']}.pdf");
} else {
  die("None shall pass");
}
?>
Mancha
fuente
5

Sam tiene la respuesta. También póngalos en un directorio con .htaccess:

Authname Private
AuthType basic
require user noadmittance

Eso evitará el acceso directo si conocen la URL. Todavía puede leerlo desde su script PHP con readfile ().

Charlie
fuente
1
Debido a su sugerencia, tuve otra idea: puse todas las facturas fuera de la carpeta www. :-) ¡Gracias de nuevo!
Frank Vilea
1
Sí, incluso mejor!
Charlie
3

Encontré esta excelente guía: Cómo servir archivos grandes a través de PHP .

Especialmente útil es el truco lighttpd: si su PHP se ejecuta bajo lighhtpd, el script solo necesita establecer el encabezado "X-Sendfile", y lighttpd leerá y enviará el archivo por usted (y bien sabe cómo enviar archivos).

ACTUALIZAR:

Lighttpd tiene esta característica y hay un mod_xsendfile para Apache2.

(Citado de la documentación de NginX )

Sandman4
fuente
0

Mi función con detección automática de tipo MIME:

function serve_file($filepath, $new_filename=null) {
    $filename = basename($filepath);
    if (!$new_filename) {
        $new_filename = $filename;
    }
    $mime_type = mime_content_type($filepath);
    header('Content-type: '.$mime_type);
    header('Content-Disposition: attachment; filename="downloaded.pdf"');
    readfile($filepath);
}

uso:

serve_file("/no_apache/invoice27342.pdf");

Presta atención para no enviar nada más con PHP (sin eco).

Samuel Dauzon
fuente