2012-03-07 37 views
5

Estoy buscando la manera más eficiente de escribir los contenidos del flujo de entrada de PHP en el disco, sin usar gran parte de la memoria que se otorga al script PHP. Por ejemplo, si el tamaño de archivo máximo que se puede cargar es de 1 GB, PHP solo tiene 32 MB de memoria.PHP usando fwrite y fread con el flujo de entrada

define('MAX_FILE_LEN', 1073741824); // 1 GB in bytes 
$hSource = fopen('php://input', 'r'); 
$hDest = fopen(UPLOADS_DIR.'/'.$MyTempName.'.tmp', 'w'); 
fwrite($hDest, fread($hSource, MAX_FILE_LEN)); 
fclose($hDest); 
fclose($hSource); 

¿Frecuenta dentro de un fwrite como el código anterior muestra que significa que todo el archivo se cargará en la memoria?

Para hacer lo contrario (escritura de un archivo - el flujo de salida), PHP ofrece una función llamada fpassthru que creo que no se sostiene el contenido del archivo en la memoria del script PHP.

Estoy buscando algo similar pero en reversa (escribiendo desde flujo de entrada al archivo). Gracias por cualquier ayuda que pueda dar.

Respuesta

3

Yep - fread usado de esa manera leería primero hasta 1 GB en una cadena, y luego lo escribiría de nuevo a través de fwrite. PHP no es lo suficientemente inteligente como para crear un conducto con memoria eficiente para usted.

me gustaría probar algo parecido a lo siguiente:

$hSource = fopen('php://input', 'r'); 
$hDest = fopen(UPLOADS_DIR . '/' . $MyTempName . '.tmp', 'w'); 
while (!feof($hSource)) { 
    /* 
    * I'm going to read in 1K chunks. You could make this 
    * larger, but as a rule of thumb I'd keep it to 1/4 of 
    * your php memory_limit. 
    */ 
    $chunk = fread($hSource, 1024); 
    fwrite($hDest, $chunk); 
} 
fclose($hSource); 
fclose($hDest); 

Si usted quería ser realmente exigente, que podría también unset($chunk); dentro del bucle después fwrite para garantizar absolutamente que PHP libera la memoria - pero que shouldn No será necesario, ya que el siguiente ciclo sobrescribirá cualquier memoria que esté siendo utilizada por $chunk en ese momento.

+0

Gracias pauld, me gusta tu idea de usar unset también. – Lakey

+1

@pauld ¡Agradable! Para obtener el mejor rendimiento, el desarmado debe usarse más como 'while (...) {...} unset ($ chunk);' reasignando la memoria cada iteración no tendría mucho impacto, pero liberando esa memoria _after_, es un poco más importante aquí. –

+0

@TonyChiboucas ¿Por qué liberarías 1024 bytes de memoria? – marijnz0r

Cuestiones relacionadas