Как лучше всего хранить загруженные изображения, базу данных SQL или файловую систему на диске? [закрыто]

148

Я пишу приложение, которое позволяет пользователям загружать изображения на сервер. Я ожидаю около 20 изображений в день в формате jpeg и, вероятно, без редактирования / изменения размера. (Это другой вопрос, как изменить размер изображений на стороне сервера перед сохранением. Может быть, кто-нибудь может добавить ресурс .NET для этого в комментарии или около того). Теперь мне интересно, где лучше всего хранить загруженные изображения.

  • Сохраните изображения в виде файла в файловой системе и создайте запись в таблице с точным путем к этому изображению.

  • Или сохраните само изображение в таблице, используя тип данных «изображение» или «двоичные данные» сервера базы данных.

Я вижу преимущества и недостатки в обоих. Мне нравится а), потому что я могу легко перемещать файлы, и мне просто нужно изменить запись в таблице. С другой стороны, мне не нравится хранить бизнес-данные на веб-сервере, и я действительно не хочу подключать веб-сервер к любому другому источнику данных, который содержит бизнес-данные (по соображениям безопасности). Мне нравится б) потому что вся информация в одном месте и легко доступны по запросу. С другой стороны, база данных очень скоро станет очень большой. Передать эти данные на аутсорсинг будет сложнее.

Тобиас
источник
2
Не нашел, где?
Тобиас
6
Здесь stackoverflow.com/questions/3748/…
Джейсон Сальдо

Ответы:

97

Я обычно храню файлы в файловой системе, потому что это то, для чего она там, хотя есть исключения. Для файлов файловая система является наиболее гибким и производительным решением (обычно).

Есть несколько проблем с хранением файлов в базе данных - файлы, как правило, намного больше, чем средняя строка - наборы результатов, содержащие много больших файлов, будут занимать много памяти. Кроме того, если вы используете механизм хранения, который использует блокировку таблиц для записи (например, ISAM), ваша таблица файлов может часто блокироваться в зависимости от размера / скорости файлов, которые вы там храните.

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

Эран Гальперин
источник
7
Не могли бы вы объяснить мне последний абзац (относительно безопасности) с точки зрения технических деталей, или любые указатели будут очень полезны. Спасибо.
VishwaKumar
40
(Для всех вас, гуглеров). Если у вас есть корень вашего сайта, настроенный на «общедоступную» папку (как в my_website / public / вместо просто my_website /), вы можете хранить изображения в папке my_website / my_images вместе с остальными ваше приложение. Тогда ваши теги img будут ссылаться на my_website / image.php? Img_id = 55 вместо my_website / avatar.png, а ваш скрипт image.php после проверки ваших учетных данных и анализа переданного вами идентификатора вернет фактический образ. Таким образом, изображение будет доступно для просмотра только зарегистрированному пользователю.
Captain Hypertext
8
эй, капитан, вы должны превратить это в настоящий ответ, чтобы получить очки $$$
Эндрю
5
пожалуйста, добавьте еще несколько примечаний о безопасности / предотвращении разрушения файлов на вашем веб-сайте
Эндрю
1
Это не масштабируется, существует ограничение на количество файлов в папке, и если вы планируете разделить свои файлы на несколько папок, это усложнит индексацию файлов (чтобы определить, где на самом деле хранится файл). Более того, поиск будет очень медленным.
Hardik
44

Единственное преимущество варианта B - наличие всех данных в одной системе, но это ложное преимущество! Вы можете возразить, что ваш код также является формой данных и, следовательно, также может храниться в базе данных - как бы вы этого хотели?

Если у вас нет уникального случая:

  • Бизнес-логика принадлежит коду.
  • Структурированные данные принадлежат базе данных (реляционной или нереляционной).
  • Объемные данные принадлежат хранилищу (файловой системе или другому).

Файлы, код, данные

Для хранения файлов необязательно использовать файловую систему. Вместо этого вы можете использовать облачное хранилище (например, Amazon S3 ) или инфраструктуру как услугу поверх него (например, Uploadcare ):

https://uploadcare.com/upload-api-cloud-storage-and-cdn/

Но хранить файлы в базе данных - плохая идея.

Давид Авсаджанишвили
источник
16

Я знаю, что это старый пост. Но многие посетители этой страницы не получают ничего, связанного с этим вопросом. Специально для новичка.

Как загружать и хранить изображения или файлы на нашем сайте:

Для статического веб-сайта, возможно, нет проблем, поскольку файловое хранилище для некоторого общего хостинга все еще достаточно. Проблема возникает из-за динамического веб-сайта, когда он становится больше. Можно обрабатывать большие файлы в базе данных, но большие файлы, такие как изображения, становятся проблемой. На веб-сайте есть два типа изображений:

  1. Изображения поступают от администратора динамического блога. Обычно эти изображения оптимизируются перед загрузкой.

  2. Изображения от пользователей в случае, если пользователям разрешено загружать изображения, такие как аватар. Или пользователи могут создавать контент для блога и размещать изображения из текстового редактора. Такого рода изображения сложно предугадать размер. Пользователи могут загружать большие изображения только для небольшого содержимого, изменяя размер представления, но не изменяя размер изображения.

Путем игнорирования пункта № 1 выше, быстрое решение для позиции № 2 можно временно решить с помощью следующих советов, если на нашем веб-сайте нет функции оптимизатора изображений:

  1. Не позволяйте пользователям загружать файлы напрямую из текстового редактора, перенаправляя их в галерею изображений. На этой странице пользователи должны загрузить файл заранее, прежде чем они смогут встроить его в контент. Этот метод называется файловым менеджером.

  2. Используйте функцию обрезки изображения, чтобы пользователи загружали изображения. Это ограничит размер изображения, даже если пользователи загружают очень большие файлы. Окончательное изображение является результатом обрезанного изображения. Мы можем определить размер на стороне сервера и принять только, например, 500 КБ или меньше.

Теперь это только временно. Для окончательного решения вопрос повторяется:

  • Как работать с большим хранилищем изображений?
  • Измените размер или измените расширение.
  • Как большой или средний веб-сайт или электронная коммерция обрабатывают файловое хранилище для своих изображений?

Что мы можем тогда сделать:

  1. Миграция с виртуального хостинга VPS. Недостаточно? Затем еще больше, перейдя на Dedicated.

  2. Создайте свой собственный сервер для хранения файлов. Погуглить, чтобы это сделать. Это не так сложно, как вы думаете. Некоторые люди делают это для своего сайта.

  3. Самый простой способ - использовать службу хранения файлов CDN.

Хорошо, 1 и 2 немного дороже. Но № 3 я считаю лучшим решением.

Некоторые сервисы CDN позволяют хранить сколько угодно веб-файлов.

Вопрос "как с нашего сайта загрузить файл в CDN?"

Не волнуйтесь, как только вы зарегистрируетесь, обычно бесплатно, вы получите руководство, как загрузить файл и получить ссылку с / на ваш сайт. Вы получите API и многое другое. Это просто.

Некоторые провайдеры предоставляют нам бесплатную услугу в течение 14 дней с ограниченным объемом памяти и пропускной способностью. Но это будет нормально для отправной точки. Единственная проблема в том, что «люди никогда не пробуют».

Надеюсь, это поможет новичку.

Сулунг Нугрохо
источник
13

У нас были клиенты, которые настаивали на варианте B (хранилище базы данных) несколько раз на нескольких разных серверах, и в конечном итоге мы всегда возвращались к варианту A (хранилище файловой системы).

Такие большие большие двоичные объекты просто не обрабатывались достаточно хорошо даже SQL Server 2005, который является последним из тех, что мы опробовали.

В частности, мы видели серьезное раздувание и, я думаю, проблемы с блокировкой.

Еще одно замечание: если вы используете хранилище на основе NTFS (сервер Windows и т. Д.), Вы можете подумать о том, чтобы найти способ разместить тысячи и тысячи файлов в одном каталоге. Я не уверен, почему, но иногда файловая система не справляется с этой ситуацией. Если кто-то знает об этом больше, я хотел бы это услышать.

Но я всегда стараюсь использовать подкаталоги, чтобы немного разбить вещи. Для этого часто подходит дата создания:

Изображения / 2008/12/17 / .jpg

... Это обеспечивает приличный уровень разделения, а также немного помогает при отладке. Клиенты Explorer и FTP могут немного задохнуться, когда каталоги действительно огромны.

РЕДАКТИРОВАТЬ: Небольшое примечание на 2017 год, в более поздних версиях SQL Server есть новые параметры для обработки большого количества BLOB, которые должны избегать недостатков, которые я обсуждал.

РЕДАКТИРОВАТЬ: краткое примечание для 2020 года, хранилище BLOB-объектов в AWS / Azure и т. Д. Также было вариантом в течение многих лет. Это отлично подходит для многих веб-проектов, поскольку это дешево и часто может упростить некоторые проблемы, связанные с развертыванием, масштабированием до нескольких серверов, отладкой других сред, когда это необходимо, и т. Д.

Брайан Маккей
источник
4
Хорошее предупреждение о количестве файлов в одном каталоге. Это может привести к ошибкам, которые трудно найти в производственной среде.
digao_mb
1
Я сталкивался с этой проблемой раньше. NTFS вела себя непредсказуемо с примерно 10 000 файлов в папке.
Faiz
2
Не только NTFS, но и BTRFS, которая также имеет проблемы с обработкой огромного количества изображений в одной папке. А именно, если вы попытаетесь lsэто сделать, это займет вечность (зависает). Или удалите.
sunapi386 06
11

Недавно я создал приложение PHP / MySQL, которое хранит файлы PDF / Word в таблице MySQL (до сих пор размером 40 МБ на файл).

Плюсы:

  • Загруженные файлы реплицируются на сервер резервного копирования вместе со всем остальным, отдельная стратегия резервного копирования не требуется (спокойствие).
  • Настроить веб-сервер немного проще, потому что мне не нужно иметь папку uploads / и сообщать всем моим приложениям, где она находится.
  • Я могу использовать транзакции для редактирования, чтобы улучшить целостность данных - мне не нужно беспокоиться о потерянных и потерянных файлах

Минусы:

  • mysqldump теперь занимает очень много времени, потому что в одной из таблиц содержится 500 МБ файловых данных.
  • В целом не очень эффективна память / процессор по сравнению с файловой системой

Я бы назвал свою реализацию успешной, она учитывает требования к резервному копированию и упрощает структуру проекта. Производительность устраивает 20-30 человек, использующих приложение.

слишком много php
источник
7

Я использую загруженные изображения на своем веб-сайте и определенно скажу вариант а).

Еще одна вещь, которую я настоятельно рекомендую, - это немедленно изменить имя файла с того, что пользователь назвал фотографии, на что-то более управляемое. Например, что-то с датой и временем для однозначной идентификации каждого изображения.

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

барфун
источник
7

Определенно измените размер изображения и проверьте его формат, если можете. Были случаи, когда вредоносные файлы загружались и обслуживались невольными хостами - например, уязвимость GIFAR позволяла скрыть вредоносный Java-апплет в файле GIF, который затем мог бы читать файлы cookie в текущем контексте и отправлять их на еще один сайт для атаки межсайтового скриптинга. Изменение размера изображений обычно предотвращает это, поскольку изменяет встроенный код. Хотя эта атака была исправлена ​​патчами JVM, наивное обслуживание двоичных файлов без их очистки открывает вам целый ряд уязвимостей.

Помните, что большинство антивирусных сканеров могут работать только с файловой системой - если вы храните свои двоичные файлы в БД, вы не сможете легко запустить сканер против них.

Тим Хоуленд
источник
5

Это в основном я.

  1. Сохраните загруженное изображение во временном каталоге или в памяти.
  2. Обработайте это изображение перед тем, как сохранить его. 2.1. Цветовая коррекция 2.2. Сжать 2.3. Создать несколько копий исходя из размеров изображения 2.4. Переименовать с суффиксами .xl, .lg, .md, .sm и т. Д.
  3. Упакуйте все обработанные файлы изображений (из одного файла) в папку с именем папки, idкоторое будет храниться в базе данных для любой строки / документа вместе с image file name(или может иметь произвольное имя в качестве имени изображения).
  4. Создайте папку yyyy / mm / d, path если она не существует. Например 2016/08/21. Запомните этот путь и сохраните в базе данных для того же документа и строки.
  5. Переместите idпапку с изображениями в pathпапку. (Папка пути может находиться в папке / var / web-content.)
  6. Очистить буфер памяти или удалить временный файл.

Когда вам нужно получить доступ к любому изображению, упомянутому в документе, у вас есть путь и идентификатор папки, которая содержит изображения. Например/var/web-content/{{path}}/{{id}}/image-file-name.sm.jpg

Таким образом, если вам нужно удалить все обработанные файлы изображений, просто удалите папку и ее содержимое рекурсивно.

Удай Хиварале
источник
4

В SQL Server 2008 есть своего рода гибридный подход, называемый типом данных файлового потока , о котором говорилось на RunAs Radio # 74 , который является своего рода лучшим из обоих миров. У большинства людей нет версии 2008 года, но если у вас есть, этот вариант выглядит довольно круто.

Чарльз Грэм
источник
3

Большинство реализаций - это вариант А.

С вариантом B вы открываете целую банку whoop4ss, когда собираете эти биты из базы данных во что-то, что может быть отображено в браузере ... Кроме того, если db не работает, изображения недоступны.

Я не думаю, что пространство - это слишком большая проблема ... Терабайтные диски сейчас стоят пару сотен долларов.

Мы реализуем вариант А, потому что у нас нет времени или ресурсов для реализации варианта Б.

мсон
источник
3

Для автоматического изменения размера попробуйте imagemagick ... он используется для многих основных систем управления контентом / фотографиями с открытым исходным кодом ... и я считаю, что для него есть некоторые расширения .net.

jle
источник
2

Мы используем A. Я бы поместил его на общий диск (если вы не планируете запускать более одного сервера).

Если придет время, когда это не будет масштабироваться для вас, вы можете изучить механизмы кеширования.

Csexton
источник
2

Абсолютно, положительно, вариант А. Другие отмечали, что базы данных обычно плохо справляются с большими двоичными объектами, независимо от того, предназначены они для этого или нет. С другой стороны, файловые системы живут ради этого. У вас есть возможность использовать чередование RAID, распределять образы по нескольким дискам, даже распределять их по географически разрозненным серверам.

Еще одно преимущество заключается в том, что резервное копирование / репликация вашей базы данных будет чудовищным.

dj_segfault
источник
2

По соображениям безопасности также рекомендуется избегать проблем, вызванных анализом содержимого IE, который может позволить злоумышленникам загружать JavaScript внутри файлов изображений, которые могут выполняться в контексте вашего сайта. Таким образом, вы можете захотеть как-то преобразовать изображения (обрезать / изменить их размер) перед их сохранением, чтобы предотвратить такого рода атаки. У этого ответа есть и другие идеи.

День
источник
2

Ну, у меня есть аналогичный проект, где пользователи загружают файлы на сервер. На мой взгляд, вариант а) - лучшее решение, так как он более гибкий. Что вам нужно сделать, так это хранить изображения в защищенной папке, классифицированной по подкаталогам. Главный каталог должен быть настроен администратором, так как контент не должен запускаться скриптами (очень важно) и (чтение, запись) защищен, чтобы он не был доступен в HTTP-запросе.

Я надеюсь, это поможет вам.

домоиндал
источник
1

Если это небольшие файлы, которые не нужно редактировать, вариант B - неплохой вариант. Я предпочитаю писать логику для хранения файлов и решения безумных проблем со структурой каталогов. Имея много файлов в одном каталоге плохо. емкай?

Если файлы большие или требуют постоянного редактирования, особенно в таких программах, как офис, то вариант А - ваш лучший выбор.

В большинстве случаев это вопрос предпочтений, но если вы выберете вариант A, просто сделайте так, чтобы в каталогах не было слишком много файлов. Если вы выберете вариант B, то сделайте таблицу с данными в формате BLOB в ее собственной базе данных и / или группе файлов. Это поможет с обслуживанием, особенно резервным копированием / восстановлением. Ваши обычные данные, вероятно, довольно малы, в то время как данные вашего изображения со временем будут огромными .

Чарльз Грэм
источник
1

Это зависит от ваших требований, особенно от объема, пользователей и частоты поиска. Но для малого или среднего офиса лучшим вариантом является использование таких приложений, как Apple Photos или Adobe Lighroom. Они специализируются на хранении, каталогизации, индексировании и организации такого рода ресурсов. Но для крупных организаций с высокими требованиями к хранению и большим количеством пользователей рекомендуется создать экземпляр платформы управления контентом с помощью системы управления цифровыми активами, например Nuxeo или Alfresco; оба предлагают очень хорошие ресурсы, действительно управляют очень большими объемами данных с помощью упрощенных методов их получения. И, что очень важно: для обеих платформ есть бесплатный вариант (с открытым исходным кодом).

Карлос Камарго
источник