Php, file загрузить
Я использую загрузку простого файла script:
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
Он работает на моем локальном сервере до 200 мб.
Когда я пытаюсь использовать этот код на своем веб-сайте, он загружает 173 КБ вместо 200 МБ файла.
Я все проверил, написал какой-то пользовательский код (используя функции ob и fread вместо readfile), но не могу загрузить большие файлы.
Спасибо за ваши ответы.
- Я использую Apache 2.2, PHP 5.3
- Все настройки PHP для работы с большими файлами в порядке. (время выполнения, пределы памяти,...
Ответы
Ответ 1
Одна из проблем, у меня есть следующий код: вы не имеете контроля над выходным потоком, позволяя PHP обрабатывать его, не зная точно, что происходит в фоновом режиме:
Что вам нужно сделать, так это настроить систему вывода, в которой вы можете управлять и реплицировать серверы accros.
Например:
if (file_exists($file))
{
if (FALSE!== ($handler = fopen($file, 'r')))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked'); //changed to chunked
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//header('Content-Length: ' . filesize($file)); //Remove
//Send the content in chunks
while(false !== ($chunk = fread($handler,4096)))
{
echo $chunk;
}
}
exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";
Это только базовая задача, но приготовьтесь!
Также прочитайте мой ответ здесь: file_get_contents = > PHP Неустранимая ошибка: допустимая память исчерпана
Ответ 2
Кажется, что readfile может иметь проблемы с длинными файлами. Как сказал @Khez, возможно, что script работает слишком долго. Быстрый поиск в Google привел пару примеров фрагментации файла.
http://teddy.fr/blog/how-serve-big-files-through-php
http://www.php.net/manual/en/function.readfile.php#99406
Ответ 3
Одно из решений некоторых сценариев состоит в том, что вы можете использовать PHP- script, чтобы разумно решить, какой файл загружать, но вместо отправки файла непосредственно с PHP вы можете вернуть перенаправление клиенту, который затем содержит прямая ссылка, которая обрабатывается только веб-сервером.
Это можно сделать по крайней мере двумя способами: либо PHP- script копирует файл в "зону загрузки", которая, например, может быть очищена из "старых" файлов регулярно каким-либо другим фоном/службой script или вы открываете реальное постоянное место для клиентов.
Конечно, есть недостатки, как в случае с каждым решением. В этом заключается то, что в зависимости от клиентов (завиток, wget, GUI-браузера), запрашивающих файл, они могут не поддерживать перенаправление, которое вы делаете, а в другом - файлы очень подвержены внешнему миру и могут быть прочитаны всегда без (доступ) для управления PHP script.
Ответ 4
Вы уверены, что ваш script может работать достаточно долго и иметь достаточно памяти?
Вам действительно нужна буферизация вывода?
Ответ 5
Реальное решение состоит в том, чтобы избежать использования PHP script для просто отправки файла клиенту, он переполняется, и ваш веб-сервер лучше подходит для задачи.
Предположительно, у вас есть причина для отправки файлов через PHP, возможно, сначала пользователи должны пройти аутентификацию? Если это так, вы должны использовать X-Accel-Redirect (если вы используете nginx) или X-Sendfile (ранее X-LIGHTTPD-send-file) на lighttpd.
Если вы используете Apache, я нашел несколько ссылок на mod_xsendfile, но я никогда не использовал его лично, и я сомневайтесь, что он установлен для вас, если вы управляете хостингом.
Если эти решения несостоятельны, я извиняюсь, но мне действительно нужна дополнительная информация о реальной проблеме: почему вы отправляете эти файлы через PHP в первую очередь?