2011-01-25 13 views
14

Tengo un script PHP que ocasionalmente necesita escribir archivos de gran tamaño en el disco. Usando file_put_contents(), si el archivo es lo suficientemente grande (en este caso alrededor de 2 MB), el script PHP se queda sin memoria (PHP Fatal error: Tamaño de memoria permitido de ######## bytes agotado). Sé que podría aumentar el límite de memoria, pero eso no me parece una solución completa, tiene que haber una mejor manera, ¿no?¿Cuál es la mejor manera de escribir un archivo grande en un disco en PHP?

¿Cuál es la mejor manera de escribir un archivo grande en un disco en PHP?

+1

¿Cuál es la fuente de los datos? Además, la mayoría de las configuraciones de PHP deberían poder manejar 2MB sin problema. Su límite de memoria puede estar muy por debajo. – webbiedave

+1

¿De dónde viene el archivo? Si ya existe en el disco, 'copy()' sería el más apropiado. – mario

+0

En este caso, obtengo el archivo de un servidor remoto usando curl. Entonces, lo tengo en una variable. –

Respuesta

15

Usted necesitará un archivo temporal en el cual pone los bits del archivo de origen, más lo de que se anexará:

$sp = fopen('source', 'r'); 
$op = fopen('tempfile', 'w'); 

while (!feof($sp)) { 
    $buffer = fread($sp, 512); // use a buffer of 512 bytes 
    fwrite($op, $buffer); 
} 

// append new data 
fwrite($op, $new_data);  

// close handles 
fclose($op); 
fclose($sp); 

// make temporary file the new source 
rename('tempfile', 'source'); 

de esta manera, todo el contenido de source no se leen en la memoria. Al usar cURL, es posible omitir la configuración CURLOPT_RETURNTRANSFER y en su lugar, añadir un búfer de salida que escribe en un archivo temporal:

function write_temp($buffer) { 
    global $handle; 
    fwrite($handle, $buffer); 
    return ''; // return EMPTY string, so nothing's internally buffered 
} 

$handle = fopen('tempfile', 'w'); 
ob_start('write_temp'); 

$curl_handle = curl_init('http://example.com/'); 
curl_setopt($curl_handle, CURLOPT_BUFFERSIZE, 512); 
curl_exec($curl_handle); 

ob_end_clean(); 
fclose($handle); 

Parece como si siempre echo de menos lo obvio. Como señaló Marc, hay CURLOPT_FILE para escribir directamente la respuesta al disco.

+0

Tiene sentido, pero en este caso he recuperado el archivo de un servidor diferente usando curl, por lo que ya está en la memoria. –

+0

@Joe Actualicé la respuesta. Otra sugerencia que viene camino. –

+0

para la primera solución que puede haber usado ['stream_copy_to_stream'] (http://php.net/stream_copy_to_stream) también ;-) – arnaud576875

1

línea de escritura por la línea (o paquete por paquete en el caso de los archivos binarios) utilizando funciones como fwrite()

0

Trate this answer:

$file = fopen("file.json", "w"); 

    $pieces = str_split($content, 1024 * 4); 
    foreach ($pieces as $piece) { 
     fwrite($file, $piece, strlen($piece)); 
    } 

    fclose($file); 
Cuestiones relacionadas