Как хранить файлы в mysql

Обновлено: 04.07.2024

Современные базы данных могут хранить самые различные виды информации. В том числе, целые файлы.

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

Современные системы управления, базами данных, включая Microsoft SQL Server (MS SQL), и средства программирования прекрасно справляются с данной задачей.

Существуют два способа хранения файлов в базах данных MS SQL.

  • Хранение файла в поле с двоичными данными (тип данных VARBINARY(MAX));
  • Использование файловых таблиц.

Второй способ стал доступен вместе с появлением файловых таблиц в MS SQL 2012 и в более ранних версиях его использование не возможно. Первый способ поддерживают все без исключения версии MS SQL (включая 2014) и он является, по сути, универсальным. Именно он и будет рассмотрен в данной статье.

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

Так как файлы могут иметь значительный размер лучше для их хранения создать отельную таблицу. Для удобства можно добавить в эту таблицу поле с именем файла или его расширением. Дело в том, что в поле с двоичными данными сохраняется только содержимое файла. Поэтому информация о его имени и расширении может оказаться весьма полезной в последующей работе. Особенно при выгрузке файла из базы данных обратно на диск.

Вот примерный вариант такой таблицы:

  • id – уникальный идентификатор. Первичный ключ;
  • fileName – строковое поле (например, nvarchar(255)) с именем файла;
  • binaryData – поле с двоичными данными (VARBINARY(MAX)) в котором собственно и хранится файл.

В этой статье я расскажу, как сохранять двоичные данные, такие как изображения в базе данных MySQL. Вы узнаете, как передать данные через HTML-форму в базу данных, извлекать и выводить их пользователю.

Прежде всего, Вы должны создать новую базу данных, для хранения бинарных данных. Для примера используется следующая таблица. Зайдите в phpMyAdmin, скопируйте и вставьте ниже приведённый код:

Пример php скрипта для сохранения данных в базе данных

Скрипт store.php сохраняет изображение в базу данных переданное через html форму.

Поскольку скрипту необходимо "знать", который файл извлекать, в качестве параметра необходимо указать его ID. Например: Файл сохранен в базе данных под ID 2. Для получения этого файла необходимо вызвать:

Если в базе данных сохранены изображения, на вашей веб-странице можно использовать скрипт getdata, как например : Например: В базе данных вы сохранили изображение как ID 3 и хотите, чтобы оно отобразилось на вашей веб-странице. Для этого воспользуйтесь следующим кодом:

Пару полезных советов.

Как сохранить файл, размер которого больше 2 Mб?

Для загрузки и сохранения файлов, чей размер превышает 2 Мб, необходимо внести несколько изменений в скрипт и php/sql настройки в связи с установленными по умолчанию ограничениями. Для хранения файлов размером 2 Мб следует сделать следующее:

Внесите изменения в скрипт store.php. Поменяйте значение MAX_FILE_SIZE на 24000000;

По умолчанию php позволяет передовать файлы размером не более 2 Мб. Необходимо изменить переменную максимального размера файла на 24M. Это можно сделать в php.ini в дириктиве setting upload_max_filesize или в .htaccess прописать строчку php_value upload_max_filesize 24M. В конфигурационных файле apache прописать LimitRequestBody 24000000.

По умолчанию в mysql можно импортировать файлы размером не более 2 Мб. Чтобы снять ограничения размера пакета в mysql, выполните слудующие действия. Откройте файл настройки my.ini, измените строчку innodb_additional_mem_pool_size = 24M

Чтобы изменения вступили в силу, перезагрузите веб сервер Apache и сервер базы данных MySQL.

Для хранения изображений в базе данных MySQL необходимо определить одно из полей таблицы как производное от типа BLOB. Сокращение BLOB означает большой двоичный объект. Тип хранения данных BLOB обладает несколькими вариантами:

  • TINYBLOB - может хранить до 255 байт
  • BLOB - может хранить до 64 килобайт информации
  • MEDIUMBLOB - до 16 мегабайт
  • LONGBLOB - до 4 гигабайт

Соответсвенно, для хранения изображений нам надо создать таблицу images с двумя полями:

  • id - уникальный ID изображения
  • content - поле для хранения изображения

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

<form enctype = "multipart/form-data" method = "post" action = "putimage.php" >
Изображение: <input type = "file" name = "image" / >
<input type = "submit" value = "Загрузить" / >
</form>

Обработчик формы - файл putimage.php:

Извлечь сохраненный файл изображения можно следующим образом (файл image.php):

Чтобы вывести изображение в HTML-документе, делаем так:

И последнее: графические файлы иногда имеют довольно большой размер, убедитесь, что настройки сервера позволяют работать с таким объемом данных. В файле php.ini это директивы post_max_size - определяет максимальный объем данных передаваемых методом POST, и upload_max_filesize - определяет максимальный размер загружаемого файла. Так же проверьте, позволяют ли настройки MySQL обрабатывать запросы с большим объемом данных (директива max_allowed_packet файла my.ini).

Комментариев: 59

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

admin:

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

Почему тогда хранят файлы в базе данных? Дело в том, что на некоторых хостингах на объем дискового пространства есть ограничения, в то время как на размер БД - нет. Подчеркиваю - на некоторых. В этом случае, чтобы не выйти за пределы дисковой квоты прибегают к такой хитрости - хранят файлы в БД. В противном случае смысла в этом нет.

Владимир Лапшин:

admin:

Согласен, сам читал об этом, но частенько забываю. Здесь это тем более актуально - нам нужно выбрать всего одно поле. Исправил.

Анатолий:

Здравствуйте. Помогите начинающему. Загрузка картинки в базу идет нормально (вроде бы), т.е. объем загруженного файла (8кб) соответствует объему картинки, но плучить изображение обратно я не могу. В приведенном вами файле image.php - $_GET - не существует. Я малость его изменил - убрал лишние пока проверки - в результате, файл выводится, но не в виде картинки, а в виде текста-абракадабры.
Привожу свой вар. подскажите где ошибка, если знаете.

admin:

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

Анатолий:

Я полагал, что перед header нельзя делать какой-либо вывод.
Впрочем, я убрал принт, оставил только одно echo - результат тот же.

admin:

P.S. Такие вопросы лучше обсуждать на форуме.

Анатолий CMX:

Спасибо! То что нужно! Все работает без правок и добавлений. Как семпл очень полезно и информативно!

не знаю толково или нет, но думаю что прокомментировал в тему!

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

victor:

Хранить изображения в базе очень удобно. Насчёт загрузки сервера - это миф. Использую MSSQL 2005 и RAID 5, база около 20Г.

admin:

victor, а в чем удобство-то? Какое реальное преимущество мы получаем, если изображение у нас в таблице БД, а не просто в директории?

victor:

Дмитрий:

Убогое какое-то описание, а где в скрипте соединение с базой данных, выбор таблицы. Уж если описываете, так сделайте чтобы даже военным было понятно

Сергей:

при переходе с MSSQL на MySQL столкнулся с проблемой, select count(*) from image; (посчитать количество картинок в базе) на MySQL выполняется 25 сек, на MSSQL MySQL меньше секунды. в таблице 50000 картинок, 300MB.
это нормально для mysql? или я что-то не так делаю?

admin:

Mujeek:

Mujeek:

Mujeek:

Будут ли кэшироваться на клиенте изображения, полученные из базы данных,или при каждом открытии страницы все изображения закачиваются заново?

admin:

Ренат:

Mujeek:

И как получить увеличенную картинку в отдельном окне при клике на изображении?

hannibal:

Очень нужно. Подскажите как вывести несколько изображений из базы.

Максим:

Сделал, подобие примера. Точнее повторил все точно точно также но вот вывода картинки я не вижу.
Загружаеться но вывода нет.
В чем может быть проблема? картика 64кб, поле(блоб).

qip 439_810-757 Мучаюсь 2 день, прошу помощи.

admin:

admin:

Максим, давайте обсудим это на форуме. Выкладывайте свой скрипт, посмотрим, в чем там проблема.

Евгений:

> при переходе с MSSQL на MySQL столкнулся с проблемой,
> select count(*) from image; (посчитать количество
> картинок в базе) на MySQL выполняется 25 сек, на
> MSSQL MySQL меньше секунды. в таблице 50000 картинок, 300MB.
> это нормально для mysql? или я что-то не так делаю?

Не так делаете. Зачем запрашивать все поля *?
Проще и быстрее будет SELECT COUNT(`id`) FROM `image`;

Sancho:

Sancho:

не пойму почему не передает полный текст

admin:

Sancho, а Вы о чем вообще говорите?

Ольга:

Скажите, что делать с хедером, если изображение мне нужно вывести в середине страницы и, естественно, заголовок уже выведен.
При инклюде image.php, вылезает ошибка - Warning: Cannot modify header information - headers already sent by (output started at Z:\home\localhost\www\xyxa\index.php:17) in Z:\home\localhost\www\xyxa\image.php on line 13
Как мне всё же вывести изображение из БД в index.php?
(И, мало ли у кого есть готовый пример для ресайза изображения ДО добавления его в БД - буду очень признательна. Хотелось бы из одной загружаемой человеком фотографии сделать превью и фото, к примеру 600х400 и поместить их в БД, причем учитывая, что просто уменьшение может оказаться не пропорциональным, если, к примеру, фото было 1200х1000)Спасибо.

admin:

если изображение мне нужно вывести в середине страницы и, естественно, заголовок уже выведен. При инклюде image.php, вылезает ошибка - Warning: Cannot modify header information
По-моему, в заметке четко написано: чтобы вывести изображение в HTML-документе, делаем так

у кого есть готовый пример для ресайза изображения ДО добавления его в БД
Масштабирование изображений

Ольга:

Включать изображение на страницу с помощью include?! Даже не комментирую…
Спасибо за быстрый ответ, но Вы не поняли, я не изображение же вставляю include, а файл image.php, а в самом html коде, конечно же.

admin:

<?php
// здесь какой-то код
?>
<html>
<head>
.
</head>
<body>
<?php
// здесь еще какой-то код
?>
Изображение:<br/>
<img src= "image.php?id=17" alt= "" />
<?php
// и еще немного
?>
</body>
</html>

Ольга:

Не злитесь, пожалуйста, я только учусь (( Я поняла свою ошибку, спасибо. Правда изображение все равно не выходит, но уже нет того, что было )) Буду разбираться дальше. СПАСИБО.

admin:

Правда изображение все равно не выходит
Что, Данила-мастер, не выходит каменный цветок?
Вывод картинок из БД - там есть рабочий пример.

Ольга:

))) С таким огромным трудом.
Но, благодаря Вам - легче! ))

Алексей:

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

admin:

Если Вы не отправляли такой заголовок - для меня полная загадка, откуда взялся диалог.

Sancho:

Подскажите пожалуйста - в форму вставки изображения можно добавить текстовые поля, чтобы их передать одновременно в фаил обработчик?

Sancho:

Да с изображением все работает отлично огромное спасибо.

admin:

в форму вставки можно добавить текстовые поля
Почему нет? Вот здесь можно посмотреть рабочий пример: Вывод картинок из БД

Sancho:

Тогда прости за наглость есче вопрос как ограничить на размер загружаемой картинки

admin:

Sancho:

Огромное человеческое СПАСИБО.

Sancho:

Можно еще один вопрос. Можно ли дать пользователю, просмотреть в браузере, загружаемое изображение до отправки на сервер! Чтобы он увидел сразу как оно будет выглядеть

admin:

Можно ли дать пользователю, просмотреть в браузере, загружаемое изображение до отправки на сервер
Нет.

Sancho:

Ответ исчерпываюше но и нато большое спасибо не будем питатся и тратит время отсутсвие результата ето тоже результат!

А что надо поменять, если нужно загрузить в БД не картинку, а файл xls?

admin:

А что надо поменять, если нужно загрузить в БД не картинку, а файл xls
Поле BLOB предназначено для хранения бинарных данных; не имеет значения, что это будет - изображение, PDF-документ или таблица Excel.

Андрей:

здравствуйте!
Подскажите пожалуйста, почему то фото не добавляется в БД. Вручную вставил фото в БД 250 кб, при этом БД жутко тормозит (страница грузилась с минуту, хотя выполнение запроса пишет 0.3 сек), и фото не выводит. Код image.php в точности как у Вас, а в файле индекс, где должно вывестись фото одна строчка

Андрей:

admin:

Андрей, рабочий пример можно взять здесь: Вывод картинок из БД. Если что-то не работает, давайте обсудим на форуме.

Света:

Хочу вывести изображение добавленное только что пользователем вместе с другими (текстовыми) полями, т.е пользователь должен увидеть загруженные им данные включая изображение (только его данные и изображение)

Короче вместо хочу использовать переменную $id

admin:

как определить автоматически присвоенный ID?
Функция mysql_insert_id().

Александр:

а как узнать ширину и высоту загруженной картинки в базе?

slogic:

Пример записи в базу не очень удачный. Картинка, не смотря на то, что исходно находится на диске, грузится полностью в память, и лишь потом в базу. Это не проблема, когда кратинка равна 250КБ, однако она может быть и 4МБ и больше. Тогда вы столкнетесь с нехваткой памяти на дешевых хостингах. Поэтому неплохо было бы дополнить пример загрузкой бинарных данных прямо с диска. Возможно такое на MySQL?

Ольга:

Здравствуйте! Я новичок, и что-то не совсем поняла как мне создать таблицу в базе, напишите пример пожалуйста!

Вот так или возможно я ошибаюсь:

База данных MySQL работает с несколькими видами хранилищ данных. Хранилища отличаются способом хранения данных, набором возможностей.

Хранилище MyISAM поддерживается сервером MySQL начиная с третьей версии. По своей сути оно организовано чрезвычайно просто, а потому с его помощью можно добиться очень высокой производительности, особенно при выборе данных из таблиц. С другой стороны, добавление данных в таблицу влечет за собой блокировку всей таблицы, поэтому одновременное добавление и выбор данных из одной и той же таблицы ведет к задержке выбора данных.

Вторым по популярности хранилищем MySQL является InnoDB. Это хранилище устроено гораздо более сложным образом. Производительность при выборе данных из таблиц в нем ниже, чем в MyISAM, зато таблицы не блокируются при изменении данных и одновременные добавления в таблицу не блокируют операции чтения из нее. Более того, InnoDB полностью поддерживает транзакции со всеми четыремя уровнями изоляции и ссылочную целостность.

Хранилище Falcon

Новое хранилище Falcon было добавлено в сервер в версии 5.2. Оно разрабатывалось исходя из мысли, что оборудование за последние несколько лет претерпело большие изменения, и, если использовать его возможности, реально создать хранилище с поддержкой большой функциональности и при этом с сохранением высокой производительности.

В настоящее время (5.2.0-alpha), хранилище находится в состоянии alpha, т.е. в нем нет всей запланированной функциональности и возможны ошибки кода. Тем не менее, эта версия позволяет оценить будущее хранилище и понять, насколько оно хорошо будет подходить к использованию с вашими приложениями.
Запланированная функциональность Falcon

При разработке Falcon планировалось создать следующую функциональность:

* полная поддержка транзакций (full ACID)
* поддержка ссылочной целостности таблиц
* хранение всех типов данных MySQL
* оптимизации для работы с большим количеством оперативной памяти
* полная мультиверсионность, позволяющая уменьшить, а иногда полностью устранить необходимость в блокировках
* сжатие данных

К сожалению, в alpha-версии воплощена не вся задуманная функциональность. Так в текущей версии не работает ссылочная целостность и нету поддержки уровня изоляции транзакций SERIALIZABLE. Тем не менее, первые три уровня изоляции работают так, как и ожидается.

Falcon в файловой системе

В файловой системе Falcon создает автоматически по три файла для каждой базы данных, использующей таблицы Falcon. В данной версии никакие характеристики этих файлов не могут быть настроены. В дальнейшем планируется возможность настройки двух файлов. В отличие от InnoDB, в котором Вы должны настроить пространство данных, Falcon создает файлы по мере необходимости.

Пусть мы создаем Falcon-таблицу в базе данных test:

При этом сервер автоматически создает следующие файлы в каталоге данных:

* test/tbl.frm — файл структуры таблицы, такой же, как и для других типов хранилищ
* test.fts — файл данных Falcon (содержит данные, индексы и прочую информацию о всех таблицах Falcon в базе test)
* test.fl1, test.fl2 — файлы журналов Falcon (содержат журналы транзакций, которые используются для отката и применения транзакций)

Очевидно, что отсутствие возможности настройки названий этих файлов приводит к ограничению на переносимость таблиц и баз данных на другие диски (в MyISAM, например, можно переносить отдельные таблицы на другие физические диски, увеличивая производительность, а в InnoDB — отдельные файлы данных). Вы все еще можете воспользоваться методом переноса файлов в UNIX-системах с помощью символических ссылок, однако для Windows рабочего метода пока еще нет (и не работает старый метод переноса всех баз данных, т.к. файлы данных Falcon хранятся вне основного каталога базы).

Оптимизации Falcon

Несмотря на многие указанные ограничения, хранилище Falcon создавалось как хранилище более быстрое, чем InnoDB. Скорость работы Falcon во многом зависит от того, какое количество памяти вы выделяете для его работы. Вы можете настроить ресурсы хранилища (так же, как и для любого другого хранилища), установив значения серверных переменных.

Помимо различных переменных, предназначенных для разработчиков, в этом списке есть переменные, которые непосредственно влияют на производительность хранилища. Это переменные falcon_max_record_memory, falcon_min_record_memory и falcon_page_cache_size.

Первые две переменные ограничивают размер памяти, которое хранилище использует для кэширования данных, индексов и прочей информации из базы данных для быстрого обращения к ним. В отличие от InnoDB, в этот кэш попадают только реально запрашиваемые данные. Те столбцы, которые Вы не используете, в кэш не попадут.

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

Работа Falcon с диском

При работе с диском, Falcon использует огромное количество оптимизаций. Самое большое время в работе БД с диском занимает поиск нужной дорожки. Falcon оптимизирован таким образом, чтобы уменьшить количество таких поисков. Например, если несколько транзакций работают одновременно, то запись журнала их работы будет произведена только при завершении одной из транзакций (ну или, разумеется, если закончится память в кэше записей).

Кэш записей содержит в себе несколько версий строк (если над ними работают разные транзакции) и индексы, связанные с этими строками. Индексы перестраиваются также в памяти и записываются вместе с завершением транзакции для уменьшения количества дисковых поисков.

При чтении и записи данных на диск, Falcon использует два потока. Один из потоков («gopher») переносит данные из кэша на диск. Он же объединяет новые индексы с индексами, хранящимися на диске. Второй поток в фоновом режиме освобождает место на диске и обновляет кэш страниц данных.

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

Заключение

К сожалению, не вся функциональность Falcon доступна. Более того, в текущей версии сервера, это хранилише не имеет многих оптимизаций для сравнения скорости с другими хранилищами. Тем не менее, Falcon показывает очень хорошие результаты при работе с кэшами. Он отлично работает с тремя уровнями изоляции и впоследствии вполне сможет стать хорошей заменой для InnoDB.

Читайте также: