Como detectar o suporte X-Accel-Redirect (Nginx) / X-Sendfile (Apache) em PHP?

Sobre a Aplicação

Estou trabalhando em uma aplicação de comércio eletrônico em PHP. Para manter o URL seguro, os links de download de produtos são mantidos atrás do PHP. Existe um arquivo, digamos download.php, que aceita alguns parâmetros via GET e verifica-os contra um database. Se tudo correr bem, ele serve arquivo usando a function readfile () em PHP.

Sobre Problema

Agora, o problema vem quando o arquivo deve ser passado para readfile () é maior do que o limite de memory definido no php.ini Como esta aplicação será usada por muitos usuários em hospedagem compartilhada, não podemos transmitir a alteração das configurações do php.ini.

No nosso esforço para encontrar soluções alternativas, pensei primeiro que podemos ir para chamadas fread () no loop while, mas parece que irá impor problemas, bem como destacados aqui. Baixando arquivos grandes de forma confiável em PHP

Então, minha melhor opção é detectar / verificar se o servidor suporta o X-Accel-Redirect (no caso do Nginx) / X-Sendfile (no caso do Apache)

Se o servidor suportar o X-Accel-Redirect / X-Sendfile, posso usá-los e, em caso de bloqueio, posso informar o administrador do sistema sobre o limite de memory imposta por php.ini

Idealmente, eu quero usar o suporte do lado do servidor como X-Accel-Redirect / X-Sendfile sempre que possível, e se isso não funcionar – eu gostaria de ter um código de retorno para ler arquivos sem readfile ().

Ainda não estou certo de como readfile () e fread () in while loop são diferentes, mas parece que o loop while irá criar o problema, novamente, como sugerido no Download de arquivos grandes de forma confiável no PHP

Espero obter alguma ajuda, sugestões, códigos, orientação.

Obrigado pela leitura.

Para detectar se o módulo apache mod_xsendfile instalado, você pode tentar este código:

if function_exists('apache_get_modules') && in_array('mod_xsendfile', apache_get_modules()) { header("X-Sendfile"); } 

Mas este código apenas verifique se o módulo está instalado apenas, que pode causar erros se ele estiver instalado, mas configurado incorretamente

outra maneira possível de fazer isso para configurar variável em todo o servidor através do .htaccess do Apache:

   XSendFile On XSendFileAllowAbove On SetEnv MOD_X_SENDFILE_ENABLED 1   

e verifique se ele forma o código php:

 if ($_SERVER['MOD_X_SENDFILE_ENABLED']) { Header(...) } 

A idéia comum é a mesma para o nginx – basta passar o valor da variável de status para backend via HTTP-header ou CGI / FastCGI variável.

readfile não ocupa uma grande quantidade de memory. Ele abre o arquivo, lê uma pequena porção, grava essa porção no navegador e, em seguida, reutiliza a memory para a próxima leitura. É o mesmo que usar fread + echo em um loop while. Você não será limitado pelos limites de memory, mas você estará limitado por max_execution_time e tal.

Se você quiser usar o suporte X-Accel-Redirect (ou similar) fornecido pelo seu servidor web, envie um header como esse (para Nginx):

 header('X-Accel-Redirect: /path/to/file'); 

Sua aplicação não pode saber se o servidor é compatível com isso. Você precisará fornecer uma opção de configuração para que o administrador / instalador do seu software possa fornecer essas informações manualmente.

Você pode definir uma variável de ambiente no servidor que controla o nome do header do servidor correto (provavelmente configurado pela equipe de operações ou quem é responsável por scripts / definir o ambiente do servidor). Isso se presta a qualquer pilha que suporte arquivos com base em header, porque as pessoas que controlam essa pilha são habilitadas para tomar decisões, enquanto você apenas lê no ambiente o header.

  

Atenção: deve-se notar que este não é um movimento novato, então tenha cuidado. Muito pode dar errado usando isso se as pessoas responsáveis ​​pelo ambiente do servidor não configurá-lo provavelmente não funcionarão ou podem causar erros, mas é simples, rápido e não consigo pensar em um motivo para mudá-lo.