2012-03-07 25 views
5

Tôi đang tìm cách hiệu quả nhất để ghi nội dung của luồng đầu vào PHP vào đĩa, mà không cần sử dụng nhiều bộ nhớ được cấp cho tập lệnh PHP. Ví dụ: nếu kích thước tệp tối đa có thể được tải lên là 1 GB nhưng PHP chỉ có 32 MB bộ nhớ.PHP sử dụng fwrite và fread với luồng đầu vào

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

Có phải fread bên trong một fwrite như đoạn mã trên có nghĩa là toàn bộ tệp sẽ được tải vào bộ nhớ?

Để làm điều ngược lại (viết một tệp đến luồng đầu ra), PHP cung cấp hàm có tên fpassthru mà tôi cho rằng không chứa nội dung của tệp trong bộ nhớ của tập lệnh PHP.

Tôi đang tìm nội dung tương tự nhưng ngược lại (viết từ luồng đầu vào vào tệp). Cảm ơn bạn đã hỗ trợ bạn có thể cung cấp.

Trả lời

3

Yep - fread được sử dụng theo cách đó sẽ đọc tối đa 1 GB thành chuỗi trước và sau đó viết lại thông qua fwrite. PHP không đủ thông minh để tạo một đường ống hiệu quả cho bộ nhớ cho bạn.

tôi sẽ cố gắng một cái gì đó tương tự như sau:

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

Nếu bạn muốn trở thành thực sự kén chọn, bạn cũng có thể unset($chunk); trong vòng lặp sau fwrite để hoàn toàn đảm bảo rằng PHP sẽ giải phóng bộ nhớ - nhưng shouldn rằng không cần thiết, vì vòng lặp tiếp theo sẽ ghi đè bất kỳ bộ nhớ nào đang được sử dụng bởi $chunk tại thời điểm đó.

+0

Cảm ơn pauld, tôi cũng thích ý tưởng của bạn về việc không sử dụng nữa. – Lakey

+1

@pauld Tuyệt vời! Để thực hiện tốt nhất, unset nên được sử dụng giống như 'while (...) {...} unset ($ chunk);' tái phân bổ bộ nhớ mỗi lần lặp lại sẽ không có nhiều tác động, nhưng giải phóng bộ nhớ đó _after_, quan trọng hơn một chút ở đây. –

+0

@TonyChiboucas Tại sao bạn sẽ giải phóng bộ nhớ 1024 byte? – marijnz0r

Các vấn đề liên quan