Как лучше хранить адрес файлов/картинок в базе данных

Всегда задавался вопрос, кто как хранит ссылки на файлы/картинки в базе данных.

Я тут вижу несколько вариантов:
  1. хранить только имя картинки file.doc
  2. хранить имя картинки и путь относительно папки с загрузками certificate/file.doc
  3. хранить полный путь до файла /srv/web/.../upload/certificate/file.doc
  4. хранить всю информацию о файле в отдельной таблице, а в нужной нам таблице хранить ID этой записи
  5. менять имя картинки на ID записи в базе


Я использую 1 вариант из за его простоты и удобства использования, а какой вариант используйте вы и почему?
  • Вопрос задан
  • 20753 просмотра
Пригласить эксперта
Ответы на вопрос 11
antoo
@antoo
Использую второй вариант, в первом случае если количество файлов будет большим, то имена могут совпасть.
в 3 варианте возникнут проблемы при переезде на другой сервер. О четвертом варианте не задумывался, мне кажется что во втором все просто и понятно.
Ответ написан
Ogra
@Ogra
4й вариант.
1. В отдельной таблице можно хранить оригинальное имя файла, держа его при этом на сервере с хитрой организацией файлов, вида: /ab/bc/de/abbcde.doc
2. Оригинальное имя файла хранится, а значит, если пользователь 1 закачал file.doc, а второй пользователь закачал file.doc, то и при скачивании обоих файлов получится file.doc, а не file(1).doc
3. В таблице можно хранить md5 файла и не забивать место (или даже процессорное время, если происходит обработка картинок/видео) дубликатами.

Ну в общем, этот слой абстракции — никому не мешает.
Ответ написан
@bekbulatov
Следует иметь в виду, что первый вариант не подойдет, если необходимо хранить много картинок. Поиск в папке будет занимать внушительное время, поэтому лучше разбивать на подпапки и хранить относительный путь в БД
Ответ написан
Комментировать
@rPman
Хранить в базе смещение (можно поделить на размер сектора или больше 4096...) и размер файла, при должном красноглазии можно завернуть оба числа в 64bit long и пользоваться им как идентификатор файла, сами файлы хранить в одном большом контейнере (можно не сильно заморачиваться с файловыми системами и складывать прямо в /dev/sda), как результат — максимально быстрый доступ к файлам (быстрее — только при самостоятельной организации кеширования под задачу) и максимально неудобное обслуживание при частых удалениях/изменениях файлов (запись только в конец контейнера, по окончании места — полная реорганизация хранилища, с выдачей новых id… но это может оказаться приемлемой платой и в некоторых задачах ее даже не придется платить).

p.s. посчитали это шуткой? просто все зависит от задачи и особенностей использования данных.
Вышеописанный способ использовался достаточно давно для не web-проекта, обеспечивал 'максимальную из возможных' производительность при резервном копировании, чтении и добавлении новых файлов, позволял организовать версионность 'из каропки',…
Ответ написан
Morro
@Morro
Первый вариант более гибкий, так как путь к картинке можно указать отдельной директивой конфиг файле приложения.
Например в джанге используется второй вариант — тоже очень неплох, для каждого поля изображения, в модели, можно установить свой путь к изображению (фактически указать директорию куда будет загружаться файл, относительно общей директории загрузки).
Что же относительно полного пути — не очень удобно, так как привязка к расположения файла жосткая.
На щет 4-го варианта — это как-то странно, зачем создавать еще одну таблицу в которой хранить id записи? Сейчас не вижу смысл.
Я бы скорее использовал первый и второй вариант, а выбор между ними зависел от приложения которое я пишу. Четвертый — при условии что у меня очень много данных в таблице, которые нужны с разной степенью релевантности. Те что более востребованы были в таблице А, а те что менее — в В, и связывались по id.
Ответ написан
Комментировать
у меня микс 2+4
есть отдельная табличка photos, где хранятся урлы картинок для разных размеров(генерятся в бэкграунде)
в объектах (юзеры или что-то другое) айдишники на фотки.
название папки в которой будет хранится картинка и имя файла генерятся. названия папок имеют вид u_{user_id}, картинки — урезанный md5 от содержимого. Таким образом почти не забочусь о проверке уникальности имен.
Ответ написан
Комментировать
@ivsedm
Ну тут наверное стоит уточнить, что именно хранится в базе. Если это профиль пользователя и путь к единственной аватарке, то можно и 1 вариант использовать. Но могут возникнуть сложности, если захотите все разделять, например, по пользователям или по типам картинок (аватарки отдельно в папке avatars и т.д.). Можно конечно и в логике все это расписать, но почти наверняка будут сложности с количеством правок, если такая переделка возникнет слишком поздно. Поэтому, имхо, предпочтителен вариант 2.
А если это альбомы пользователей с произвольным количеством картинок (и нужна таблица связей), то мне больше нравится вариант 4.
Ответ написан
Комментировать
JustSkiv
@JustSkiv
Golang Senior Developer
На мой взгляд, лучший вариант — первый. Это придает гибкость организации хранения файлов. То есть, сегодня ваша папка с файлами называется — «files», а завтра вы решите её назвать «storage». Если вы при этом храните вместе с именем файла часть пути, вам придется редактировать кучу записей. Куда проще, на мой взгляд, указать путь до каталога с файлами в каком нибудь конфиге, а в базе хранить лишь имена.

Действительно, организация файлов очень упростится: например, вы сможете в любой момент рассортировать их по отдельным каталогам ('storage/music', 'storage/images' и т.п.).

> 5. менять имя картинки на ID записи в базе
Этот вариант не конфликтует с первым. Но, целесообразность такого решения зависит от конкретной ситуации.
Ответ написан
savostin
@savostin
Еще один программист
Смотря какие файлы и для чего.
Если это аватарка пользователя, то ее вообще можно не хранить — переименовываем в [ID].png и кладем в папку /avatars/ Так можно поступать со всеми файлами, привязанными к Primary Key.
Если при этом нужно сохранить имя файла, то опять же можно переименовать в ID, а в базе хранить имя (не подойдет, если у Вас кеширование).
Можно класть в папку /files/[ID]/file.png
Вобщем решение зависит от конкретной задачи.
Полный путь — это конечно же избыточность и негибкость.
Ответ написан
Комментировать
savostin
@savostin
Еще один программист
Гы, а еще файлы можно хранить прям в базе, в BLOB.
Ответ написан
Комментировать
serejatoje
@serejatoje
Я делаю так - в поле таблицы вписываю через разделитель md5 имена файлов (в общем уникальные выходят), а сами картинки лежат в папке, к примеру, images/2014/08/17/ (год/месяц/день).
Таким образом я могу вытащить любую картинку из базы, опираясь на поле date моей записи в таблице, парсим её на год, месяц и день - добавляем любое имя файла (исходя от разделителя (может быть "запятая")), и вуаля)
Кхм.. А если, к примеру, нужно брать уменьшенные копии, то просто вписываем после нашего images/2014/08/17/ (из примера) строчку "_s/". Выходит - images/2014/08/17/_s/{имя файла}. Мне кажется это достаточно удобный способ, хоть и для моих задач
Ответ написан
Ваш ответ на вопрос

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

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