Я думаю, что лучшим способом решения вашей проблемы было бы запросить серверное время и рассчитать разницу с вашим местным временем. Вы сохраняете эту разницу и всякий раз, когда вам нужно серверное время, просто добавляете разницу к вашему местному времени.
Вы не должны читать, все это - просто вводит цикл, читая его в, скажем, блоках 32 КБ и отправке его, как произведено. Еще лучше используйте fpassthru, который делает почти такую же вещь для Вас....
$name = 'mybigfile.zip';
$fp = fopen($name, 'rb');
// send the right headers
header("Content-Type: application/zip");
header("Content-Length: " . filesize($name));
// dump the file and stop the script
fpassthru($fp);
exit;
еще меньше строк, если Вы используете readfile, которому не нужен вызов fopen...
$name = 'mybigfile.zip';
// send the right headers
header("Content-Type: application/zip");
header("Content-Length: " . filesize($name));
// dump the file and stop the script
readfile($name);
exit;
Если Вы хотите стать еще более милыми, можно поддерживать заголовок Довольного Диапазона, который позволяет клиентам запросить конкретный диапазон байта файла. Это особенно полезно для обслуживания файлов PDF к Adobe Acrobat, которая просто запрашивает блоки файла, это должно представить текущую страницу. Это немного включено, но посмотрите это для примера.
Лучший способ отправить большие файлы с php X-Sendfile
заголовок. Это позволяет веб-серверу служить файлам намного быстрее через механизмы нулевой копии как sendfile(2)
. Это поддерживается lighttpd и апачем с плагином.
Пример:
$file = "/absolute/path/to/file"; // can be protected by .htaccess
header('X-Sendfile: '.$file);
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
// other headers ...
exit;
Сервер читает X-Sendfile
заголовок и отсылает файл.
В то время как fpassthru()
был мой предпочтительный вариант в прошлом, руководство PHP на самом деле рекомендует* использование readfile()
вместо этого, если Вы просто выводите файл как есть клиенту.
*
"Если Вы просто хотите вывести содержание файла к буферу вывода без первого изменения его или ищущий на конкретное смещение, можно хотеть использовать readfile (), который сохраняет Вас fopen () вызов". — Руководство PHP
Если Ваши файлы не доступны веб-сервером, потому что путь не находится в Вашем веб-каталоге обслуживания (htdocs) затем, можно сделать символьную ссылку (символьная ссылка) на ту папку в веб-каталоге обслуживания, чтобы не передавать всю транспортную канавку php.
Можно сделать что-то вроде этого
ln -s /home/files/big_files_folder /home/www/htdocs
Используя php для обслуживания статических файлов намного медленнее, если у Вас будет интенсивный трафик, то потребление памяти будет очень большим, и это не может обработать большое количество запросов.
Взгляните на fpassthru (). В более поздних версиях PHP это должно служить файлам, не сохраняя их в памяти, как этот комментарий указывает.
Одно из преимуществ fpassthru () - то, что эта функция может работать не только с файлами, но и любым допустимым дескриптором. Сокет, например.
И readfile () должен быть немного быстрее, причина использования механизма кэширования ОС, если возможный (так же как как file_get_contents ()).
Еще одна подсказка. fpassthru () содержат открытый дескриптор, пока клиент не становится довольным (который может потребовать довольно долгого времени на медленном подключении), и таким образом, необходимо использовать некоторый механизм блокировки, если параллель пишет в этот возможный файл.
Ответы Python являются всей пользой. Но есть ли какая-либо причина, Вы не можете сделать веб-доступный каталог, содержащий символьные ссылки на фактические файлы? Может потребоваться некоторая дополнительная конфигурация сервера, но это должно работать.