Рады сообщить, что проект Tracks Flow начинает поддержку Open Source сообщества. Сегодня мы выкладываем в открытый доступ простенькую разработку — сервер хранения файлов на PHP с клиентской библиотекой на C#.
Просим строго не судить — этот проект был написан очень давно и с тех пор без особых изменений использовался в fidel.ru, а затем и в tracksflow.com. Перед выкладкой в открытый доступ мы его немножко причесали.
Этот код предназначен тем, кто хочет реализовать у себя систему хранения больших (и не очень) файлов наименьшими усилиями.
Достоинства
- Компактный код — легко проверить и поправить под себя.
- Хорошая масштабируемость по количеству хранимого контента.
- Отсутствие БД.
- Возможность работы с файлами произвольного размера *.
* Единственная функция, которая может некорректно работать на больших файлах — проверка md5 суммы файла. Функция может вызывать TimeOutException.
Как работает
Загрузка файла происходит порциями данных (чанками) — по одному POST-запросу на один чанк. Загрузка происходит последовательно. При обработке очередного запроса сервер дописывает полученную часть в результирующий файл. Все операции инвариантны по времени к длине целевого файла.
Все файлы хранятся на файловой системе в структуре каталогов:
/<корневой_путь>/<scope>/<первые_два_символа_id>/<вторые_два_символа_id>/<пятый-последний_символ_id>/<filename.ext>
При загрузке файла в целевой директории создаются временные файлы, которые затем удаляются.
Скачивание файлов происходит путем передачи в Nginx заголовка X-ACCEL_REDIRECT с путем к файлу. Отгрузкой занимается сам Nginx.
Как настроить и запустить
- Ставим Nginx + php-fpm.
- В nginx создаем конфиг для хоста системы хранения примерно следующего содержания:
server { listen <your_LAN_ip>; server_name <you_file_storage_hostname>; location /<location_name> { internal; root <storage_root_path_should_be_the_same_in_lib.php>; } location ~ .php { root /<path_to_php_code>; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /<path_to_php_code>/$fastcgi_script_name; include fastcgi_params; } }
- Копируем файлы сервера в директорию <path_to_php_code>
- Проверяем lib.php – функция getfsroot() должна возвращать путь, указанный в конфиге в <storage_root_path_should_be_the_same_in_lib.php>; функция getlocroot() должна содержать то же, что указано в конфиге в <location_name>.
- Ставим права на <storage_root_path_should_be_the_same_in_lib.php> те же, что и у Nginx / php-fpm, даем право записи.
- Если мы хотим использовать чанки больше 512КБайт, то надо прописать в php-fpm, nginx и php.ini соответствующие значения для ограничений на аплоад.
Как масштабироать
При масштабировании по объему хранимых файлов возникает необходимость использовать несколько серверов. В этом случае удобно поставить на нужное количество серверов Lufs, примонтировать файловую систему на веб-сервер и работать с ней как с локальной директорией.
Use Case
С помощью этого решения мы сейчас храним аватарки пользователей и обложки плейлистов. Соответственно, используем два пространства (scope) под каждый тип сущности. Идентификатор каждой картики равен идентификатору сущности в БД. Имя файла состоит из сиснейма размера (например, ImageLarge), определяющего тип файла для сущности и расширения jpg. Такой подход позволяет зная только идентификатор сущности и имея справочник типов файлов, соответствующих сущности, сформировать ссылку на файл.
Ссылки
Git-репозиторий решения: https://github.com/tracksflow/FileStorage
Ну и, конечно, приглашаем вас на TracksFlow.com. Сервис активно развивается, так что вы точно найдете что то интересное, если давно не были. Ну а для тех, кто не был еще — сегодня раздаем инвайты всем кто пришлет запрос в личку любому сотруднику компании.
Автор: Andrey_Kuprikov