2010-02-23 13 views
5

Tratar de forzar-descarga de archivos con PHP usando habitual:¿Hay algún límite en el tamaño de un archivo cuando causa una descarga con PHP?

header("Content-type: $type"); 
header("Content-Disposition: attachment; filename=$name"); 
header('Content-Length: ' . filesize($path)); 

Y lo hace con éxito para archivos en algún lugar por debajo de 32 MB. Para los más grandes, solo devuelve un archivo en cero.

Obviamente, hay algún tipo de límite, pero ¿qué lo configura? Usando Apache 2.2.11 y PHP 5.3.0.

+0

PHP no tiene tal límite. Esto debe hacerse en serverfault ya que está relacionado con su configuración de Apache. – hobodave

Respuesta

0

Dentro del php.ini verá la configuración.

No recuerdo el nombre de la opción en la parte superior de mi cabeza, pero ahora buscaré en mi php.ini e intentaré encontrarlo.

Simplemente retíralo y funcionará.

Agregado

bien, por favor, que alguien me corrija si estoy equivocado, pero ¿es

memory_limit

+0

¿Qué? PHP no tiene una configuración de "descarga máxima" de ningún tipo. Por favor, tómese el tiempo para al menos investigar su respuesta para que realmente pueda _proveer una_. – hobodave

+0

Creo que el problema se debe a que él mismo está generando el archivo, de ahí el memory_limit anterior. Por favor, corrígeme si me equivoco porque también quiero saber esto. – Layke

+1

No hay suficiente información presente para determinar eso. memory_limit tiene que ver con la cantidad de memoria que puede usar el script. Esto solo entraría en juego si intenta leer el archivo completo en la memoria, o lo suficiente como para exceder el límite de memoria. Enviar encabezados no hace esto. – hobodave

3

Parece que va a cargar el archivo completo en la memoria RAM antes de enviar abajo al destinatario. Querrá consultar PHP Streams para poder enviar el contenido completo del archivo sin tener que leerlo todo en la RAM primero: http://php.net/streams

+0

Estoy usando fopen, fread ($ fh, $ chunksize), funciones fclose. ¿No son seguros para tales casos? – jayarjo

+0

La forma más fácil es usar 'readfile' http://php.net/manual/en/function.readfile.php – deceze

+0

Ese es un buen punto de engaño; Estoy acostumbrado a canalizar datos desde una base de datos u otra fuente, por lo que recurro a las transmisiones cuando hay una solución más simple disponible. – MightyE

8

Eventualmente tropecé con esta publicación: http://w-shadow.com/blog/2007/08/12/how-to-force-file-download-with-php/.

function output_file($file, $name, $mime_type='') 
{ 
/* 
This function takes a path to a file to output ($file), 
the filename that the browser will see ($name) and 
the MIME type of the file ($mime_type, optional). 

If you want to do something on download abort/finish, 
register_shutdown_function('function_name'); 
*/ 
if(!is_readable($file)) die('File not found or inaccessible!'); 

$size = filesize($file); 
$name = rawurldecode($name); 

/* Figure out the MIME type (if not specified) */ 
$known_mime_types=array(
    "pdf" => "application/pdf", 
    "txt" => "text/plain", 
    "html" => "text/html", 
    "htm" => "text/html", 
    "exe" => "application/octet-stream", 
    "zip" => "application/zip", 
    "doc" => "application/msword", 
    "xls" => "application/vnd.ms-excel", 
    "ppt" => "application/vnd.ms-powerpoint", 
    "gif" => "image/gif", 
    "png" => "image/png", 
    "jpeg"=> "image/jpg", 
    "jpg" => "image/jpg", 
    "php" => "text/plain" 
); 

if($mime_type==''){ 
    $file_extension = strtolower(substr(strrchr($file,"."),1)); 
    if(array_key_exists($file_extension, $known_mime_types)){ 
     $mime_type=$known_mime_types[$file_extension]; 
    } else { 
     $mime_type="application/force-download"; 
    }; 
}; 

ob_end_clean(); //turn off output buffering to decrease cpu usage 

// required for IE, otherwise Content-Disposition may be ignored 
if(ini_get('zlib.output_compression')) 
    ini_set('zlib.output_compression', 'Off'); 

header('Content-Type: ' . $mime_type); 
header('Content-Disposition: attachment; filename="'.$name.'"'); 
header("Content-Transfer-Encoding: binary"); 
header('Accept-Ranges: bytes'); 

/* The three lines below basically make the 
    download non-cacheable */ 
header("Cache-control: private"); 
header('Pragma: private'); 
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); 

// multipart-download and download resuming support 
if(isset($_SERVER['HTTP_RANGE'])) 
{ 
    list($a, $range) = explode("=",$_SERVER['HTTP_RANGE'],2); 
    list($range) = explode(",",$range,2); 
    list($range, $range_end) = explode("-", $range); 
    $range=intval($range); 
    if(!$range_end) { 
     $range_end=$size-1; 
    } else { 
     $range_end=intval($range_end); 
    } 

    $new_length = $range_end-$range+1; 
    header("HTTP/1.1 206 Partial Content"); 
    header("Content-Length: $new_length"); 
    header("Content-Range: bytes $range-$range_end/$size"); 
} else { 
    $new_length=$size; 
    header("Content-Length: ".$size); 
} 

/* output the file itself */ 
$chunksize = 1*(1024*1024); //you may want to change this 
$bytes_send = 0; 
if ($file = fopen($file, 'r')) 
{ 
    if(isset($_SERVER['HTTP_RANGE'])) 
    fseek($file, $range); 

    while(!feof($file) && 
     (!connection_aborted()) && 
     ($bytes_send<$new_length) 
     ) 
    { 
     $buffer = fread($file, $chunksize); 
     print($buffer); //echo($buffer); // is also possible 
     flush(); 
     $bytes_send += strlen($buffer); 
    } 
fclose($file); 
} else die('Error - can not open file.'); 

die(); 
} 

/********************************************* 
      Example of use 
**********************************************/ 

/* 
Make sure script execution doesn't time out. 
Set maximum execution time in seconds (0 means no limit). 
*/ 
set_time_limit(0); 
$file_path='that_one_file.txt'; 
output_file($file_path, 'some file.txt', 'text/plain'); 

Sumando todas las cabeceras recomendados allí y también usando:

ob_end_clean(); //turn off output buffering to decrease cpu usage 

antes de cualquier salida - ha ayudado. No más limitaciones observables. Los archivos se descargan completamente, incluso los más grandes.

+0

No es aconsejable usar la supresión de error '@' ya que es lenta y puede llevar a pesadillas de depuración. –

+0

Lo tengo eliminado, gracias por señalar esto :) – jayarjo

+2

#giveThisMan_a_bells! Gracias @Jayarjo, ¡esto me lo resolvió! –

0

También puede ser necesario que set_time_limit(0);

0

Hay 1 GB acumulación límite en Apache, incluso si ua intenta descargar un archivo desde que directorio raíz, evitando por completo php.

Cuestiones relacionadas