2012-03-07 20 views
5

Sto cercando il modo più efficiente per scrivere il contenuto del flusso di input PHP su disco, senza utilizzare gran parte della memoria che è concessa allo script PHP. Ad esempio, se la dimensione massima del file che è possibile caricare è 1 GB, ma solo PHP ha 32 MB di memoria.PHP utilizzando fwrite e fread con il flusso di input

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); 

Fa apparire all'interno di un fwrite come il codice precedente indica che l'intero file verrà caricato in memoria?

Per fare il contrario (scrittura di un file - il flusso di output), PHP offre una funzione chiamata fpassthru che credo non detiene il contenuto del file in memoria dello script PHP.

Sto cercando qualcosa di simile ma al contrario (scrivendo da input stream to file). Grazie per l'assistenza che puoi dare.

risposta

3

Yep - fread usato in questo modo dovrebbe leggere prima fino a 1 GB in una stringa, quindi scriverlo nuovamente tramite fwrite. PHP non è abbastanza intelligente per creare una pipe efficiente per la memoria.

vorrei provare qualcosa di simile al seguente:

$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); 

Se si voleva essere pignoli, si potrebbe anche unset($chunk); all'interno del ciclo dopo fwrite per garantire assolutamente che PHP libera la memoria -, ma che shouldn essere necessario, in quanto il ciclo successivo sovrascriverà la quantità di memoria utilizzata da $chunk in quel momento.

+0

Grazie pauld, mi piace anche la tua idea di usare unset. – Lakey

+1

@pauld Bello! Per le migliori prestazioni, l'unset dovrebbe essere usato più come 'while (...) {...} unset ($ chunk);' ridistribuendo la memoria ogni iterazione non avrebbe molto impatto, ma liberando quella memoria _after_, è un po 'più importante qui. –

+0

@TonyChiboucas Perché dovresti liberare 1024 byte di memoria? – marijnz0r

Problemi correlati