Эффективное сохранение загруженных пользователем изображений в файловой системе

сценарий

Пользователи могут публиковать элемент и включать до 5 изображений с сообщением, каждое загружаемое изображение необходимо передискретизировать и изменить размер – создано всего 4 дополнительных изображения. Значение, если пользователь загружает 5 изображений, заканчивается 25 фотографиями для хранения.

Предположения

  • Изображения были правильно проверены, и они являются действительными файлами изображений
  • Система должна масштабироваться (предположим 1000 сообщений в первом экземпляре, поэтому максимально 5000 изображений)
  • Каждое изображение переименовывается в отношении идентификатора auto_incremenet записи сообщения db и включает соответствующий суффикс, т.е. 12345_1_1.jpg 12345_2_1.jpg – поэтому нет проблем с дубликатами
  • Изображения не чувствительны, поэтому нет проблем с их непосредственным доступом (хотя список каталогов будет отключен)

Возможные подходы

  • Учитывая, что идентификаторы уникальны, мы могли бы просто отбросить их в одну папку (неэффективно после определенной точки).
  • Можно создать папку для каждого сообщения и поместить в нее все изображения, поэтому ROOT / images / 12345 (опять же, получится множество папок)
  • Возможно создание хранилища изображений на основе даты, то есть каждый день создается новая папка и хранятся изображения дней.
  • Можно сохранить изображения на основе измененного размера, т. Е. Все исходные файлы могут быть сохранены в одной папке images / orig все миниатюры в изображениях / thumb (я думаю, что Gumtree использует подобный подход).
  • Возможно, X количество файлов будет сохранено в одной папке перед созданием другого.

У кого-нибудь есть опыт в отношении лучших практик / подходов при масштабировании изображений?

Примечание. Я предполагаю, что кто-то упомянет S3 – предположим, что мы хотим сохранить изображения локально на данный момент.

Спасибо, что посмотрели

У нас есть такая система в тяжелом производстве с 30 000 + файлами и 20+ ГБ на сегодняшний день …

  Column | Type | Modifiers -------------+-----------------------------+---------------------------------------------------------- File_ID | integer | not null default nextval('"ACRM"."File_pseq"'::regclass) CreateDate | timestamp(6) with time zone | not null default now() FileName | character varying(255) | not null default NULL::character varying ContentType | character varying(128) | not null default NULL::character varying Size | integer | not null Hash | character varying(40) | not null Indexes: "File_pkey" PRIMARY KEY, btree ("File_ID") 

Файлы хранятся только в одном каталоге с целым файлом-файлом в качестве имени файла. У нас более 30 000 без проблем. Я тестировал выше, без проблем.

Это использует RHEL 5 x86_64 с ext3 в качестве файловой системы.

Я бы сделал это так снова? Нет. Позвольте мне поделиться несколькими мыслями о редизайне.

  1. База данных по-прежнему является «основным источником» информации о файлах.

  2. Каждый файл sha1 () hashed и хранится в иерархии файловой системы на основе этого хэша: /FileData/ab/cd/abcd4548293827394723984723432987.jpg

  3. база данных немного умнее в отношении хранения метаинформации по каждому файлу. Это будет трехстоловая система:

    File : сохраняет информацию, такую ​​как имя, дата, ip, владелец и указатель на Blob (sha1)
    File_Meta : сохраняет пары ключ / значение в файле, в зависимости от типа файла. Это может включать в себя информацию, такую ​​как Image_Width и т. Д. …
    Blob : сохраняет ссылку на sha1 вместе с ее размером.

Эта система будет дедуплицировать содержимое файла, сохраняя данные, на которые ссылается хеш (несколько файлов могут ссылаться на одни и те же данные файла). Было бы очень просто выполнить резервное копирование синхронизации базы данных файлов с помощью rsync.

Кроме того, ограничения данного каталога, содержащие большое количество файлов, будут устранены.

Расширение файла будет храниться как часть уникального хэша файла. Например, если хэш для пустого файла был abcd8765 … Пустой .txt файл и пустой .php файл будут ссылаться на один и тот же хеш. Скорее, они должны ссылаться на abcd8765.php и abcd8765.txt . Зачем?

Apache и т. Д. Можно настроить для автоматического выбора типов контента и правил кеширования на основе расширения файла. Важно хранить файлы с допустимым именем и расширением, которое отражает содержимое файла.

Понимаете, эта система может действительно повысить производительность, делегируя доставку файлов через nginx. См. http://wiki.nginx.org/XSendfile .

Надеюсь, это поможет в некотором роде. Береги себя.

Я бы сохранил все изображения в одной папке – база данных затем отслеживает имена файлов – держите ее простой

Во-первых, я бы рекомендовал создать таблицу для изображений. Это таблица файлов строк / изображений:

 | id | filename | type | storage | --------------------------------------- | 123 | 123.png | original | store1 | 
  • id auto incremental int или что-то уникальное.
  • filename файла. Это позволяет переместить файл и просто обновить код. Имя файла может быть {file_id}.{extension} .
  • type – это тип изображения: original , thumbnail , resized , resized . Также могут быть размеры: 100x100 , x500 , x500 (где 500x будет неограниченной высоты, а x500 – неограниченной шириной). Это лишь некоторые примеры.
  • storage будет идентификатором для файла, это может быть каталог. Скажем, что вы сохраняете свои изображения в post_images , имя файла – 123.png а хранилище – store1 , тогда путь будет post_images/store1/123.png .

Мне еще предстоит попробовать это, но у меня проблемы с веб-приложениями, хранящими 10k + файлы в том же каталоге.