Очень большие загрузки с PHP
Я хочу разрешить загрузку очень больших файлов в наше PHP-приложение (сотни мегабайт - 8 гигабайт). Однако с этим есть пара проблем.
Браузер:
- У загрузок HTML дрянная обратная связь, нам нужно либо опросить о прогрессе (что немного глупо), либо вообще не показывать обратную связь
- Загрузчик Flash помещает весь файл в память перед началом загрузки
Сервер:
- PHP заставляет нас устанавливать post_max_size, что может привести в легко эксплуатируемой DOS-атаке. Я бы не хотел устанавливать этот параметр глобально.
- Серверу также требуются некоторые другие переменные, которые должны присутствовать в POST vars, такие как секретный ключ. Мы хотели бы иметь возможность отклонить запрос сразу, а не после загрузки всего файла.
Требования:
- HTTP является обязательным.
- Я гибок в использовании клиентских технологий, пока они работают в браузере.
- PHP не является обязательным требованием, если есть какие-то другие технология, которая будет хорошо работать в среде Linux, это совершенно круто.
13 answers
Как насчет Java-апплета? Вот как мы должны были это сделать в компании, в которой я раньше работал. Я знаю, что апплеты отстой, особенно в наши дни, когда доступны все наши возможности, но они действительно являются наиболее универсальным решением проблем, связанных с десктопами, возникающих при веб-разработке. Просто есть над чем подумать.
Размер файла Upload_max_filesize может быть установлен для каждого каталога ; то же самое относится и к размеру post_max_size
Например:
<Directory /uploadpath/>
php_value upload_max_filesize 10G
php_value post_max_size 10G
</IfModule>
Обработчик Python?
Использование обработчика сообщений Python вместо PHP. Создайте уникальный идентификатор из вашего PHP-приложения, который клиент может поместить в заголовки HTTP. С помощью mod_python, чтобы отклонить или принять большую загрузку до передачи всего тела СООБЩЕНИЯ.
Я думаю http://www.modpython.org/live/current/doc-html/dir-handlers-hph.html
Позволяет проверять заголовки и отклонять остальную часть ввода сообщения. Я не пробовал, но, возможно, это правильный путь?
Глядя на источник mod_python, буферизация входных данных с помощью read(), по-видимому, позволяет поочередно оценивать входные данные HTTP. Заголовки на первом месте.
Https://svn.apache.org/repos/asf/quetzalcoatl/mod_python/trunk/src/filterobject.c
Я знаю, что это старое, но, возможно, у кого-то сейчас тоже есть эта проблема. Теперь вы можете сделать это только с помощью Javascript и, скажем, PHP. На стороне клиента не требуется Flash или Java.
Демонстрация: http://dnduploader.filkor.org/
Идея состоит в том, чтобы разрезать файлы с помощью метода Javascript Blob slice()...
Вы можете установить post_max_size только для сценариев в 1 каталоге. Поместите туда свой скрипт загрузки и разрешите только этому скрипту обрабатывать большие размеры. Этот скрипт все еще может быть атакован большими/бесполезными файлами, но он позволяет избежать его глобальной настройки.
Используйте это с APC, и вы, возможно, сможете придумать что-то хорошее: Статья IBM Developer работает над APC
Попробовал все это... это, безусловно, лучшее, что я использовал до сих пор...
Взгляните на jumploader.com
Хороший java-апплет для загрузки.
Я использовал его для загрузки изображений, и он отлично работает. Не пробовал работать с файлами размером более 10 МБ, но я должен работать и с действительно большими файлами.
Изучали ли вы возможность использования APC для проверки прогресса и общего размера файла. Вот хороший пост в блоге об этом. Это может помочь.
Возможно, вы могли бы использовать Webdav и Javascript в браузере
Загрузка большого файла AJAX с прогрессом в WebDAV
Http://www.webdavsystem.com/ajax/programming/upload_progress
Простая библиотека
Http://debris.demon.nl/projects/davclient.js/doc/README.html
Затем вы можете заставить JS перенаправить пользователя на страницу успеха. Секретные ключи и то, что не может быть обработано в прелюдии PHP перед передачей JS Клиент->WebDAV
Я бы посмотрел FTP, SSH или SCP это позволяет загружать большой файл и при этом иметь контроль доступа к файлу. Это может занять немного больше времени для реализации, но, вероятно, это самый безопасный способ, который я мог придумать.
У меня был успех с uploadify, и я бы рекомендовал это. Это скрипт jQuery/Flash, который обрабатывает большие загрузки, и вы можете передать ему дополнительные параметры (например, секретный ключ). Чтобы решить проблемы на стороне сервера, просто используйте следующий код. Изменения влияют только на сценарий, в котором они вызываются:
//Check to see if the key is there
if(!isset($_POST['secret_key']) || !isValid($_POST['secret_key']))
{
exit("Invalid request");
}
function isValid($key)
{
//Put your validation code here.
}
//This line changes the timeout.
//Give it a value in seconds (3600 = 1 hour)
set_time_limit(3600);
//Set these amounts to whatever you need.
ini_set("post_max_size","8192M");
ini_set("upload_max_filesize","8192M");
//Generally speaking, the memory_limit should be higher
//than your post size. So make sure that's right too.
ini_set("memory_limit","8200M");
ОТРЕДАКТИРУЙТЕ В ответ на ваш комментарий:
Учитывая то, что вы сказали, я боюсь, что вы не сможете выполнить свои требования по протоколу http. Все из существующих решений есть код, который добавляет в http функции, для которых он никогда не предназначался.
Как вы сами сказали, это простой протокол. Помимо написания собственного клиентского программного обеспечения, которое работает вне браузера, java-апплета или использует другой протокол (например, FTP, который был разработан для этого), вы можете не получить то, что хотите.
Я сделал все, что мог, в рамках заданных ограничений. Извини, что я не смог сделать лучше.
Я знаю, что отстойно добавлять еще одну зависимость, но, по моему опыту, большинство веб-сайтов, которые делают что-то подобное, используют flash на стороне клиента и загружают большой файл в виде фрагментов
Adobe в качестве инструкции по загрузке файлов flash
Я также нашел этот учебник по codeproject:
Загрузка Нескольких Файлов С Индикатором Выполнения С Помощью Flash и ASP.NET
PS - Я знаю, что вы используете PHP, а не .net, я подумал, что важной частью была вспышка ;)
Попробуйте это: http://www.simple2ftp.com использует FTP-апплет на основе Java из умной оболочки PHP-приложения.