Подтвердить что ты не робот

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

Сценарий

Пользователи могут публиковать элемент и включать до 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 - предположим, что мы хотим сохранить изображения локально на данный момент.

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

4b9b3361

Ответ 1

У нас есть такая система в тяжелом производстве с 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")

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

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

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

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

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

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

    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.

Надеюсь, это поможет в некотором роде. Будьте осторожны.

Ответ 2

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

Ответ 3

Сначала я бы рекомендовал создать таблицу для изображений. Это таблица файлов с одной строкой/изображением:

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

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