php - post_max_size - wordpress memory limit 40m memory_limit should be at least 96mb
¿Por qué readfile() agota la memoria PHP? (6)
Bueno, es una función con memoria intensiva. Me gustaría conectar a los usuarios a un servidor estático que tiene un conjunto de reglas específicas para controlar las descargas en lugar de usar readfile ().
Si esa no es una opción, agregue más RAM para satisfacer la carga o introduzca un sistema de colas que controle con gracia el uso del servidor.
He visto muchas preguntas sobre cómo usar PHP de manera eficiente para descargar archivos en lugar de permitir solicitudes HTTP directas (para mantener los archivos seguros, realizar un seguimiento de las descargas, etc.).
La respuesta casi siempre es PHP readfile () .
- Descargando archivos de gran tamaño de manera confiable en PHP
- ¿Cómo forzar la descarga de archivos grandes sin utilizar demasiada memoria?
- ¿La mejor forma de registrar de forma transparente las descargas?
PERO, aunque funciona de maravilla durante la prueba con archivos de gran tamaño, cuando está en un sitio en vivo con cientos de usuarios, las descargas comienzan a colgarse y los límites de memoria PHP se agotan.
Entonces, ¿qué pasa con la función readfile()
que hace que la memoria readfile()
tanto cuando el tráfico es alto? Pensé que se suponía que debía evitar el uso intensivo de la memoria PHP escribiendo directamente en el búfer de salida.
EDITAR: (Para aclarar, estoy buscando un "por qué", no "qué puedo hacer". Creo que el mod_xsendfile de Apache es la mejor manera de evitarlo )
Description
int readfile ( string $filename [, bool $use_include_path = false [, resource $context ]] )
Reads a file and writes it to the output buffer*.
PHP tiene que leer el archivo y escribir en el búfer de salida. Entonces, para un archivo de 300Mb, sin importar la implementación que hayas escrito (por muchos segmentos pequeños, o por 1 gran parte), PHP tiene que leer 300Mb de archivos eventualmente.
Si el usuario múltiple tiene que descargar el archivo, habrá un problema. (En un servidor, los proveedores de hospedaje limitarán la memoria que se le da a cada usuario de alojamiento. Con una memoria tan limitada, usar el búfer no será una buena idea).
Creo que usar el enlace directo para descargar un archivo es un enfoque mucho mejor para archivos grandes.
Es posible que desee desactivar el almacenamiento en búfer de salida para esa ubicación en particular, utilizando la directiva de configuración output_buffering de PHP .
Ejemplo de Apache:
<Directory "/your/downloadable/files">
...
php_admin_value output_buffering "0"
...
</Directory>
"Desactivado" ya que el valor parece funcionar también, mientras que realmente debería arrojar un error. Al menos según cómo otros tipos se convierten a booleanos en PHP . * se encoge de hombros *
Si tiene buffer de salida activado, use ob_end_flush () justo antes de la llamada a readfile ()
header(...);
ob_end_flush();
@readfile($file);
Terminé con esta idea en el pasado (como parte de mi biblioteca) para evitar un alto uso de memoria:
function suTunnelStream( $sUrl, $sMimeType, $sCharType = null )
{
$f = @fopen( $sUrl, ''rb'' );
if( $f === false )
{ return false; }
$b = false;
$u = true;
while( $u !== false && !feof($f ))
{
$u = @fread( $f, 1024 );
if( $u !== false )
{
if( !$b )
{ $b = true;
suClearOutputBuffers();
suCachedHeader( 0, $sMimeType, $sCharType, null, !suIsValidString($sCharType)?(''content-disposition: attachment; filename="''.suUniqueId($sUrl).''"''):null );
}
echo $u;
}
}
@fclose( $f );
return ( $b && $u !== false );
}
Tal vez esto puede darte algo de inspiración.
Como se menciona aquí: "Memoria permitida ... agotada" cuando se utiliza el archivo de lectura , el siguiente bloque de código en la parte superior del archivo php hizo el truco para mí.
Esto comprobará si el buffer de salida php está activo. Si es así, lo apaga.
if (ob_get_level()) {
ob_end_clean();
}