Como posso permitir que um usuário faça o download de um arquivo armazenado fora do webroot?

Estou desenvolvendo um sistema que permite que usuários cadastrados (quem poderia ser qualquer um) para fazer upload de arquivos. Eu bloqueio mime-types etc. para tentar restringir os arquivos aos tipos .doc, .docx e .pdf, mas para segurança adicional, eles são carregados para uma pasta fora do webroot.

Outros usuários podem optar por baixar os arquivos. Como posso permitir que façam isso? Obviamente não consigo colocar um link para o arquivo, pois está fora do webroot. Ainda não sei como chegar ao arquivo! Presumo que eu possa usar as funções do arquivo php para acessar o arquivo, mas como eu “vejo isso” para o usuário que o solicitou?

Quais as implicações de segurança que tudo isso pode ter?

Obrigado.

Você precisa de um script PHP que faça o seguinte:

  1. Defina o header do tipo de conteúdo corretamente (dependendo do que o usuário está baixando)
  2. Defina o header do comprimento do conteúdo corretamente (dependendo do tamanho do arquivo)
  3. Abra o arquivo para leitura (você pode usar fopen)
  4. Leia o arquivo e exiba seu conteúdo para o stream de saída
  5. Feito

Você também pode usar a function readfile para fazer basicamente o mesmo. Aqui está um exemplo do site do PHP:

 

Você pode colocar seu diretório de arquivos na raiz e aplicar regras de reescrita de modificação para proteger e mostrar um caminho virtual para os usuários em vez do caminho real.

Experimente o seguinte:

 $fileName = basename($_GET['file']); $path = 'path/to/data/'.$fileName; // define $mimeType and $isAuthenticated if ($isAuthenticated && file_exists($path)) { // serve file header('Content-type: '.$mimeType); header('Content-Disposition: attachment; filename="'.$fileName.'"'); readfile($path); } else { // 404 } 

Isso provavelmente precisará de mais headers para atender às suas necessidades, mas você deve ter uma idéia de como isso pode ser usado.

Veja as respostas a esta pergunta semelhante: Consulte um arquivo fora da tree do site para fins de download , que liga para a página de manual da function de header PHP .