MYSQL - ХРАНИТЬ ИЗОБРАЖЕНИЯ С ПОМОЩЬЮ BLOB

Thank you for reading this post, don't forget to subscribe!

BLOB (или Binary Large Object, боль­шой дво­ич­ный объ­ект) – это тип дан­ных MySQL, кото­рый поз­во­ля­ет хра­нить дво­ич­ные дан­ные: изоб­ра­же­ния, муль­ти­ме­диа и фай­лы PDF.

Хра­нить изоб­ра­же­ния (такие как фото­гра­фии и под­пи­си) в базе дан­ных MySQL вме­сте с дру­гой инфор­ма­ци­ей удоб­но в том слу­чае, если вы раз­ра­ба­ты­ва­е­те при­ло­же­ния с силь­ной при­вяз­кой к БД (напри­мер, пор­тал поис­ка рабо­ты, база дан­ных сту­ден­тов или финан­со­вое при­ло­же­ние), и в этой БД изоб­ра­же­ния долж­ны быть син­хро­ни­зи­ро­ва­ны с дру­ги­ми данными.

И тогда на помощь при­хо­дит тип дан­ных BLOB. Этот под­ход устра­ня­ет необ­хо­ди­мость в созда­нии отдель­ной фай­ло­вой систе­мы для хра­не­ния изоб­ра­же­ний, а так­же цен­тра­ли­зу­ет базу дан­ных, делая ее более пор­та­тив­ной и надеж­ной, посколь­ку дан­ные изо­ли­ро­ва­ны от фай­ло­вой систе­мы. А еще это упро­ща­ет созда­ние резерв­ных копий, посколь­ку вы може­те создать один дамп MySQL, содер­жа­щий все ваши данные.

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

1: Создание базы данных

Давай­те нач­нем с созда­ния тесто­вой базы дан­ных для это­го про­ек­та. Под­клю­чи­тесь к сер­ве­ру по SSH, а затем выпол­ни­те сле­ду­ю­щую коман­ду, что­бы вой­ти на сер­вер MySQL как поль­зо­ва­тель root:

sudo mysql -u root -p

Вве­ди­те root-пароль базы дан­ных MySQL и нажми­те Enter, что­бы продолжить.

После это­го выпол­ни­те сле­ду­ю­щую коман­ду, что­бы создать базу дан­ных. В этом руко­вод­стве мы назо­вем ее test_company:

CREATE DATABASE test_company;

После созда­ния БД вы уви­ди­те следующее:

Query OK, 1 row affected (0.01 sec)

Теперь нам нуж­но создать на сер­ве­ре MySQL учет­ную запись test_user; не забудь­те заме­нить PASSWORD слож­ным паролем:

CREATE USER 'test_user'@'localhost' IDENTIFIED BY 'PASSWORD';

Вы полу­чи­те сле­ду­ю­щий результат:

Query OK, 0 rows affected (0.01 sec)

Что­бы предо­ста­вить поль­зо­ва­те­лю test_user пол­ные пра­ва досту­па к базе дан­ных test_company, запу­сти­те команду:

GRANT ALL PRIVILEGES ON test_company.* TO 'test_user'@'localhost';

Вы долж­ны полу­чить сле­ду­ю­щий результат:

Query OK, 0 rows affected (0.01 sec)

В завер­ше­ние нуж­но сбро­сить таб­ли­цы при­ви­ле­гий, что­бы MySQL пере­за­гру­зил права:

FLUSH PRIVILEGES;

На экране долж­но появиться:

Query OK, 0 rows affected (0.01 sec)

Теперь, когда база дан­ных test_company и поль­зо­ва­тель test_user гото­вы, мы можем перей­ти к созда­нию таб­ли­цы. Пред­по­ло­жим, нам нуж­на таб­ли­ца products для хра­не­ния спис­ка това­ров. Поз­же мы попро­бу­ем вста­вить и извлечь дан­ные из этой таб­ли­цы, что­бы понять, как рабо­та­ет BLOB в MySQL.

Вый­ди­те из обо­лоч­ки MySQL:

QUIT;

Затем сно­ва вой­ди­те в систе­му, на этот раз – как поль­зо­ва­тель test_user:

mysql -u test_user -p

При появ­ле­нии запро­са вве­ди­те пароль test_user и нажми­те Enter, что­бы про­дол­жить. Затем открой­те базу дан­ных test_company, набрав команду:

USE test_company;

Перей­дя в базу дан­ных test_company, MySQL отоб­ра­зит такой результат:

Database changed

Затем создай­те таб­ли­цу products:

CREATE TABLE `products` (product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50), price DOUBLE, product_image BLOB) ENGINE = InnoDB;

Эта коман­да создаст таб­ли­цу по име­ни products. В таб­ли­це будет четы­ре столбца:

  • product_id: в этом столб­це исполь­зу­ет­ся тип дан­ных BIGINT, он поз­во­ля­ет вме­стить боль­шой спи­сок про­дук­тов, содер­жа­щий 2⁶³-1 эле­мен­тов. Мы поме­ти­ли стол­бец как PRIMARY KEY, что­бы при­сво­ить това­рам уни­каль­ные иден­ти­фи­ка­то­ры. Что­бы MySQL мог обра­ба­ты­вать созда­ние новых иден­ти­фи­ка­то­ров, мы исполь­зо­ва­ли клю­че­вое сло­во AUTO_INCREMENT.
  • product_name: этот стол­бец содер­жит назва­ния това­ров. Здесь мы исполь­зо­ва­ли тип дан­ных VARCHAR, так как это поле обыч­но обра­ба­ты­ва­ет бук­вен­но-циф­ро­вые зна­че­ния дли­ной до 50 сим­во­лов; огра­ни­че­ние в 50 сим­во­лов – это все­го лишь гипо­те­ти­че­ское зна­че­ние, исполь­зу­е­мое для целей это­го руководства.
  • price: этот стол­бец содер­жит роз­нич­ные цены наших това­ров. Посколь­ку цена на неко­то­рые това­ры может выра­жать­ся чис­лом с пла­ва­ю­щей точ­кой (напри­мер, 23.69, 45.36, 102.99), мы ука­за­ли здесь тип дан­ных DOUBLE.
  • product_image: в этом столб­це мы ука­за­ли тип дан­ных BLOB, посколь­ку он пред­на­зна­чен для хра­не­ния дво­ич­ных дан­ных – изоб­ра­же­ний товаров.

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

Query OK, 0 rows affected (0.03 sec)

Вый­ди­те из сер­ве­ра MySQL:

QUIT;

Вы полу­чи­те сообщение:

Bye

Таб­ли­ца products гото­ва. Вы може­те исполь­зо­вать ее для хра­не­ния неко­то­рых запи­сей, вклю­чая изоб­ра­же­ния про­дук­тов. Ско­ро мы запол­ним ее данными.

2: Создание PHP-скрипта для заполнения базы данных

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

Что­бы создать PHP-скрипт, открой­те новый файл в тек­сто­вом редакторе:

sudo nano /var/www/html/config.php

Затем вставь­те в него сле­ду­ю­щую инфор­ма­цию (заме­ни­те PASSWORD паро­лем test_user, кото­рый вы созда­ли в разделе

1):

Сохра­ни­те и закрой­те файл.

В этом фай­ле для под­клю­че­ния к базе дан­ных MySQL мы исполь­зо­ва­ли четы­ре кон­стан­ты PHP:

  • DB_NAME: эта кон­стан­та содер­жит имя базы дан­ных, test_company.
  • DB_USER: содер­жит имя поль­зо­ва­те­ля, test_user.
  • DB_PASSWORD: хра­нит пароль учет­ной запи­си test_user.
  • DB_HOST: опре­де­ля­ет сер­вер, на кото­ром нахо­дит­ся база дан­ных. В этом слу­чае это сер­вер localhost.

Сле­ду­ю­щая стро­ка в фай­ле ини­ци­и­ру­ет PHP Data Object (PDO) и под­клю­ча­ет­ся к базе дан­ных MySQL:

...

$pdo = new PDO("mysql:host=" . DB_HOST . "; dbname=" . DB_NAME, DB_USER, DB_PASSWORD);

...

Бли­же к кон­цу фай­ла мы уста­но­ви­ли пару атри­бу­тов PDO:

  • ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION: этот атри­бут гене­ри­ру­ет исклю­че­ние, кото­рое может быть заре­ги­стри­ро­ва­но и исполь­зо­ва­но в целях отладки.
  • ATTR_EMULATE_PREPARES, false: повы­ша­ет без­опас­ность, так как пере­по­ру­ча­ет под­го­тов­ку ядру базы дан­ных MySQL вме­сто PDO.

Файл /var/www/html/config.php нуж­но вклю­чить в два сце­на­рия PHP, кото­рые мы созда­дим далее. Они будут отве­чать за встав­ку и извле­че­ние запи­сей соответственно.

Сна­ча­ла создай­те PHP-скрипт /var/www/html/insert_products.php для встав­ки запи­сей в таб­ли­цу products:

sudo nano /var/www/html/insert_products.php

Затем добавь­те сле­ду­ю­щие кон­фи­гу­ра­ции в файл /var/www/html/insert_products.php:

Сохра­ни­те и закрой­те файл.

Этот файл нужен для опре­де­ле­ния пере­мен­ных базы дан­ных и под­клю­че­ния к ней. Файл так­же ини­ци­и­ру­ет объ­ект PDO и сохра­ня­ет его в пере­мен­ной $pdo. Мы ссы­ла­ем­ся на файл config.php вверху.

Затем мы созда­ли мас­сив дан­ных о това­рах, кото­рые нуж­но вста­вить в БД. Поми­мо product_name и price, кото­рые зада­ны в виде строк и чис­ло­вых зна­че­ний соот­вет­ствен­но, сце­на­рий исполь­зу­ет встро­ен­ную функ­цию PHP file_get_contents для чте­ния изоб­ра­же­ний из внеш­не­го источ­ни­ка и пере­да­чи их в виде строк в стол­бец product_image.

После это­го мы под­го­то­ви­ли опе­ра­тор SQL и исполь­зо­ва­ли опе­ра­тор PHP foreach{…} для встав­ки каж­до­го про­дук­та в базу данных.

Запу­сти­те /var/www/html/insert_products.php в окне бра­у­зе­ра, исполь­зуя сле­ду­ю­щий URL-адрес (не забудь­те заме­нить your-server-IP внеш­ним IP-адре­сом сервера):

http://your-server-IP/insert_products.php

На экране вы уви­ди­те сооб­ще­ние об успеш­ном выпол­не­нии фай­ла – сле­до­ва­тель­но, запи­си были встав­ле­ны в базу данных.

Records inserted successfully

Итак, мы успеш­но вста­ви­ли три запи­си, содер­жа­щие изоб­ра­же­ния това­ров, в таб­ли­цу. На сле­ду­ю­щем эта­пе мы напи­шем сце­на­рий PHP для извле­че­ния этих запи­сей и отоб­ра­же­ния их в браузере.

3: Извлечение и визуализация данных из БД MySQL

Имея ​в базе дан­ных инфор­ма­цию и изоб­ра­же­ния това­ров, вы може­те напи­сать вто­рой сце­на­рий PHP, кото­рый будет запра­ши­вать и отоб­ра­жать дан­ные в таб­ли­це HTML в браузере.

Что­бы создать файл, введите:

sudo nano /var/www/html/display_products.php

Затем вставь­те в файл следующее:

Сохра­ни­те изме­не­ния в фай­ле и закрой­те его.

Мы сно­ва сосла­лись на файл config.php для под­клю­че­ния к базе дан­ных. Затем мы с помо­щью PDO созда­ли и выпол­ни­ли опе­ра­тор SQL для извле­че­ния всех эле­мен­тов из таб­ли­цы; это дела­ет­ся при помо­щи коман­ды SELECT * FROM products.

Затем мы созда­ли таб­ли­цу HTML и запол­ни­ли ее дан­ны­ми о това­рах с помо­щью PHP-опе­ра­то­ра while() {…}. Стро­ка $row = $stmt->fetch(PDO::FETCH_ASSOC) запра­ши­ва­ет БД и сохра­ня­ет резуль­тат в пере­мен­ной $row в виде мно­го­мер­но­го мас­си­ва, кото­рый затем отоб­ра­жа­ет­ся в столб­це таб­ли­цы HTML с помо­щью $row[‘column_name’].

Изоб­ра­же­ния из столб­ца product_image заклю­че­ны в теги <img src = “”>. Мы зада­ли атри­бу­ты шири­ны и высо­ты, что­бы умень­шить раз­мер изоб­ра­же­ний (ина­че бы они не поме­сти­лись в столб­це таб­ли­цы HTML).

Что­бы пре­об­ра­зо­вать дан­ные, содер­жа­щи­е­ся в типе BLOB, обрат­но в изоб­ра­же­ния, мы исполь­зо­ва­ли встро­ен­ную PHP функ­цию base64_encode и сле­ду­ю­щий син­так­сис для схе­мы Data URI:

data:media_type;base64, base_64_encoded_data

В этом слу­чае image/png – это media_type, а стро­ка в коди­ров­ке Base64 из столб­ца product_image – это base_64_encoded_data.

Запу­сти­те файл display_products.php в веб-браузере:

http://your-server-IP/display_products.php

После запус­ка фай­ла display_products.php вы уви­ди­те в бра­у­зе­ре HTML-таб­ли­цу со спис­ком това­ров и их изображениями.

Это зна­чит, что наш сце­на­рий PHP пра­виль­но извле­ка­ет и визу­а­ли­зи­ру­ет изоб­ра­же­ния и дру­гие дан­ные MySQL