PHP: servir um arquivo para download sem fornecer o link direto

12

Desejo veicular faturas para download. Atualmente, estou usando um esquema de numeração simples (invoice-01.pdf, invoice-02.pdf e assim por diante). Eu sei que eu poderia usar hashes para ocultar os dados.

Também é possível usar o PHP e exibir as faturas por não ter o usuário apontado diretamente para elas?

Frank Vilea
fonte
Sim. Que tal " invoices.invalid /… "?
mailq

Respostas:

26

Existe até um exemplo disso no 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');
?> 

Ou expanda isso um pouco com

<?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
fonte
5

Sam tem a resposta. Coloque-os também em um diretório com .htaccess:

Authname Private
AuthType basic
require user noadmittance

Isso impedirá o acesso direto se eles souberem o URL. Você ainda pode lê-lo a partir do seu script PHP com readfile ().

Charlie
fonte
1
Por causa da sua sugestão, tive outra ideia: coloquei todas as faturas fora da pasta www. :-) Obrigado novamente!
Frank Vilea 29/09/11
1
Sim ainda melhor!
Charlie
3

Encontrei para este excelente guia: Como servir grandes arquivos através do PHP .

Especialmente útil é o truque do lighttpd - Se o seu PHP for executado sob o lighhtpd, o script precisará apenas definir o cabeçalho "X-Sendfile", e o lighttpd lerá e enviará o arquivo para você (e ele sabe como enviar arquivos).

ATUALIZAR:

O Lighttpd possui esse recurso e existe um arquivo mod_xsend para o Apache2.

(Citado na documentação do NginX )

Sandman4
fonte
0

Minha função com detecção 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");

Preste atenção para não enviar mais nada com PHP (sem eco).

Samuel Dauzon
fonte