2010-12-13 3 views
3

Многие пользователи моего сайта сообщили о проблемах с загрузкой большого файла (80 МБ). Я использую принудительную загрузку с использованием заголовков. При необходимости я могу предоставить дополнительные настройки php. Я использую CakePHP framework, но этот код является обычным php. Я использую php 5.2 с apache на выделенном виртуальном сервере из медиа-храма CentOS Linux. Видите ли вы какие-либо проблемы со следующим кодом:Принудительная загрузка большого файла с помощью php

 set_time_limit(1500); 
     header("Content-Type: application/octet-stream"); 
     header("Content-Disposition: attachment; filename=\"" . basename($file_path) . "\""); 
     header("Content-Length: ".$content_length); 
     header("Content-Transfer-Encoding: binary"); 
     header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
     header('Cache-Control: private', false); 
     header('Pragma: public'); 
     header('Expires: 0'); 

     //Change this part 
     $handle = fopen($file_path, 'rb'); 
     while (!feof($handle)) 
     { 
      echo fread($handle, 4096); 
      ob_flush(); 
      flush(); 
     } 
     fclose($handle); 
     exit; 

В принципе, проблема сообщается, что начинается загрузка, а затем останавливается в середине. Я думал, что это проблема с лимитом, поэтому я добавляю код set_time_limit. Раньше я использовал функцию чтения php, но это также не работало плавно.

+0

Как насчет 'set_time_limit (0)'? – alex

+0

Какова точка цикла для вывода файла, если вы не возражаете, чтобы я спросил? –

+0

@ElYobo Мое предположение, поэтому он не потребляет слишком много памяти сразу. – alex

ответ

4

Проблема с PHP инициированной передачи HTTP является то, что они редко поддерживают частичные запросы:

GET /yourfile HTTP/1.1 
Range: bytes=31489531-79837582 

Всякий раз, когда браузер сталкивается с проблемой передачи, он попытается возобновить загрузку. Ваш php-скрипт не подходит для этого (это не тривиально, поэтому никто не делает).

Так что действительно избегайте этого. Перенаправить пользователей в статический файл и позволить веб-серверу обрабатывать его. Если вам необходимо обработать авторизацию, используйте трюки, такие как символические ссылки или перезаписывающие устройства, которые проверяют файлы cookie сеанса или даже файл статического разрешения (./allowed/178.224.2.55-file-1). Любые требуемые дополнительные заголовки HTTP могут быть введены аналогичным образом или с файлом .meta.

+0

Интересная идея; знаете ли вы конкретный пример этого? –

+1

@ElYobo: для трюка разрешения .htaccess может быть достаточно простого 'RewriteCond -f ./allow -% {REMOTE_ADDR}'. Поддержка байтовых диапазонов находится в Nanoweb и PEAR HTTP_Server IIRC. Но быстрый google дает: http://www.coneural.org/florian/papers/04_byteserving.php – mario

+0

Прохладный, спасибо. Мне нужна дополнительная безопасность, чем пример RewriteCond (например, несколько пользователей за прокси-сервером), но статья интересна. –

1

Я не вижу никаких проблем, но для S & G попытается установить set_time_limit внутри цикла while. Это гарантирует, что они не достигнут жесткого предела и (пока клиент принимает информацию) срок продлевается.

+0

Вы можете просто использовать 'set_time_limit (0)', чтобы не налагать ограничений по времени. – alex

+0

Я, как правило, обнаруживаю, что идея группы, в случае операции рук (по любой причине). Я стараюсь всегда давать PHP возможность сократить галстук, иначе (по какой-то причине) что-то пойдет не так, и у вас есть нить, просто сидевшая там бездействующая. –

+0

сколько секунд, на ваш взгляд, я должен продлить? возможно, 5-10? – jimiyash

Смежные вопросы