Как организовать хранение фотографий для сайта?

Предполагается хранить файлы на собственном сервере (NodeJS).
Объем — несколько десятков тысяч, т.е простейший вариант сваливать все в одну директорию уже не подходит. Кроме того, для файлов с изображениями нужно хранить тубмы.

Я сейчас вижу примерно такой алгоритм после того, как файл получен от клиента:
1) Вычислить хеш от изображения
2) По хешу определить путь до папки (как описано здесь, второй способ)
3) Сделать нужные тубмы и сохранить все это рядом. Примерно так:
../6a/c1/e68d51251ab2d826ce8d0b92dd08a7e01c3d.jpeg
../6a/c1/e68d51251ab2d826ce8d0b92dd08a7e01c3d_100x100.jpeg
../6a/c1/e68d51251ab2d826ce8d0b92dd08a7e01c3d_200x200.jpeg


Первый вопрос общий: насколько этот способ актуален и есть ли у него достойные альтернативы?

И второй: как реализовать саму файловую структуру?
fs.writeFile('/home/nodejs/project/static/6a/c1/e68d51251ab2d826ce8d0b92dd08a7e01c3d_100x100.jpeg, buffer, err => {
            if (err) console.error(err.message);
        });


Показанный выше код, естественно, выдаст ошибку, т.к. директории ../6a/c1/ еще не существует. Решать банальной проверкой наличия директории? Или, может быть, создавать директории по другому принципу?
  • Вопрос задан
  • 1740 просмотров
Решения вопроса 1
@dimuska139
Backend developer
Загружайте файлы не в папку, а в s3-совместимое хранилище (чтобы при желании можно было без страданий и изменений в коде перейти на Amazon или в Linode какой-нибудь) - MinIO. Т.е. генерируете некий id, превращаете его в хеш, формируете ключ и по нему льёте в MinIO. Причём храните только оригиналы.

Что касается миниатюр, то их нарезать и хранить не нужно. Представьте, если размеры в дизайне поменялись - что тогда? А если для каждой миниатюры webp-версия потребовалась - все картинки опять обрабатывать? Есть решение - imgproxy. Это специальный прокси-сервис (можно на свой сервер поставить, как и MinIO), который нарезает картинки "на лету" в момент обращения (по параметрам в url). Кроме нарезки, есть ещё куча разных возможностей. Кеша внутреннего нет, т.е. перед imgproxy есть смысл поставить Nginx для кеширования миниатюр (чтобы при каждом обращении не нарезало).
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
ThunderCat
@ThunderCat Куратор тега Веб-разработка
{PHP, MySql, HTML, JS, CSS} developer
Вариантов масса, каждый из которых зависит от кучи нюансов и тонкостей проекта.
Суть одна - директория для хранения не должна содержать в себе большой объем файлов, что достигается распределением файлов между поддиректориями.
Принцип создания поддиректорий не суть важен, можно создавать по датам например, типа /16112021/ или более ветвистое 2021/11/16/, как собственно и тумбы - можно создавать как хеш+размер, а можно все как одинаковое название (тот же хеш), но хранить в подпапках размера, типа: /16112021/100x100/e68d51251ab2d826ce8d0b92dd08a7e01c3d.jpeg, что достаточно просто позволит работать с тумбами, зная только фуллсайз картинку.

Короче вариантов масса, какой подходит вам сказать сложно, просто следуйте логике и здравому смыслу.
Ответ написан
Комментировать
firedragon
@firedragon
Не джун-мидл-сеньор, а трус-балбес-бывалый.
Вот одна из реализаций
https://qna.habr.com/q/673339

Также можно попробовать azure blob storage.
Ответ написан
Комментировать
ASultonov
@ASultonov
Тоже считаю второй способ самым оптимальным. Когда-то смотрел разные варианты и остановился на этом. Генерируется уникальный ID, создаются директории для равномерного распределения согласно второму способу из stackoverflow... а дальше можно посмотреть по ссылкам (w - width, высота зависит от пропорций изображения):
// ID: 3d02573d-4d28-7144-9f6e-f7372a084069
// Путь: [uploads]/[первые два символа ID]/[след. два символа ID]/[ID]/[что угодно][разделитель][разрешение][расширение]
{
	...
	photos: [{
		original: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_4032x3024.jpg',
		w1024: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_1024x768.jpg',
		w600: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_600x450.jpg',
		w256: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_256x192.jpg',
		w56: '/uploads/3d/02/3d02573d-4d28-7144-9f6e-f7372a084069/3d02573d_56x42.jpg'
	}]
	...
}

Можно удалить фотографию вместе с тумбами за раз удалив папку 3d02573d-4d28-7144-9f6e-f7372a084069.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы