Как правильно хранить изображения на сервере?

103
30 июня 2021, 14:20

Требуется загрузить изображение в MySQL через форму :

<p>
    <span class='ttl'>Постер<span style="color:red;">*</span></span>
    <span class='fld'>
<input id='picture' type='file' charset="base64" placeholder="example@email.com" class="field"/>
</span>
</p>

Код загрузки:

<?php
// Устанавливаем соединение с базой данных
require_once("connect.php");
try {
// 1. Проверяем, переданы ли POST-параметры;
// если ответ положительный, помещаем новое
// сообщение в базу данных
    if(!empty($_POST))
    {
        $error = [];
        if(empty($_POST['creator'])) {
            $error[] = "Отсутствует автор статьи";
        }
        if(empty($_POST['title'])) {
            $error[] = "Отсутствует название статьи";
        }
        if(empty($_POST['picture'])) {
            $error[] = "Отсутствует постер статьи";
        }
        if(empty($_POST['category'])) {
            $error[] = "Отсутствует категория статьи";
        }
        if(empty($_POST['text_paper'])) {
            $error[] = "Отсутствует текст статьи";
        }
// Если нет ошибок, помещаем сообщение
// в базу данных
        if(empty($error))
        {
            $query = "INSERT INTO
paper
VALUES (
:category,
:creator,
NOW(),
:title,
:text_paper,
:picture,
NULL)";
            $usr = $pdo->prepare($query);
            $usr->execute([
                'category' => $_POST['category'],
                'creator' => $_POST['creator'],
                'title' => $_POST['title'],
                'text_paper' => $_POST['text_paper'],
                'picture' => $_POST['picture'],
            ]);
        }
    }
} catch (PDOException $e) {
    echo "Ошибка выполнения запроса: " . $e->getMessage();
}
?>

Если грузить изображение через PhpMyAdmin то все работает корректно

Но если грузить через форму на сайте, то выводит следующее:

Изображения хранятся в формате BLOB, единственный способ что нашел на просторах интернета основывается на этом, при том что большие изображения грузить не представляется возможным. Если есть (наверняка) более лучший способ реализовать загрузку/выгрузку в/из MySQL буду рад ссылкам на ресурсы.

Answer 1
Пошаговый, быстрый гайд, по хранению изображений на сервере

1. HTML форма

За загрузку изображений у нас отвечает input с атрибутом type="file", так же существует атрибут name="foo", есть также допольнительные атрибуты, на подобии required, или accept="image\*". Создаем форму загрузки изображения:

<form action="upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="myFile" accept="image/*" required>
    <input type="submit" value="Upload">
</form>
  • method="post" - Задаем метод отправки POST, именно его, следуя спецификации RFC 7231
  • type="file" - Задаем тегу input тип, в данном случае тип file
  • name="file" - Задаем имя, для того чтобы в PHP потом получить отправленное изображение
  • type="submit" - Задаем тип тегу input как submit, он просто сгенерирует кнопку с событием, по нажатию, наша форма отправится на скрипт upload.php
  • enctype="multipart/form-data" - ОБЯЗАТЕЛЬНО, это передача заголовков о загрузке изображения, без нее загрузка работать не будет!!!

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

2. База данных(MySQL)

Хранить изображения в талице в формате BLOB - одна из самых глупых и плохих реализаций данной задачи. Поэтому будем хранить путь(В дальнейшем path) до нашего изображения на сервере. Наша таблица image будет иметь такую структуру:

CREATE TABLE dbname.image (
  id INT(11) NOT NULL AUTO_INCREMENT,
  path VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (id)
)
ENGINE = INNODB;
  • id - Уникальный индентефикатор картинки
  • path - Путь до нашей картинки на сервере, к примеру /uploads/image_foobar.jpg

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

3. Скрипт загрузки (Upload.php)

Скрипт будет предельно простой, без проверок на уже созданное имя файла и прочее, для подключения к базе будем использовать PDO и подготовленные запрос, далее в коде оставил комментарии:

<?php
if($file = $_FILES['myFile']) {
    // Получаем наше изображение, имя которого мы указали в атрибуте `name="file"`
    $path =  __DIR__ . '/uploads/'; // Наш путь до папки загрузок
    $fileExt = end(explode('.', $file['name']));  // Получили расширение файла `jpg`
    $fileName = uniqid('image_') . "." . $fileExt;    // Сгенерировали уникальное имя нашему файлу, с расширением
    try {
        // Создаем экземпляр класса PDO
        $pdo = new PDO(
            'mysql:host=localhost;dbname=dbname',
            'root',
            ''
        );
        $sql = 'INSERT INTO `image`(path) VALUES(?)';   // Создаем SQL-запрос для вставки имени изображения
        $stmt = $pdo->prepare($sql);    // Подготавливаем наш запрос
        $stmt->execute([$fileName]);    // Выполняем наш запрос
        move_uploaded_file($file['tmp_name'], $path.$fileName); // Сохраняем картинку на сервере в '/uploads/'
    } catch (Exception $e) {
        echo $e->getMessage();
    }
}

4. Итоги

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

Я показал как реализовать самую базовую загрузку и хранение изображений на сервере, ее оптимизация, а также реализация загрузки сразу несколькиз файлов - зависит от вашей фантазии, пробуйте и эксперементируйте. Хорошего вам изучения и программирования). Спасибо большое за прочтение "мини-поста" :)

READ ALSO
Получить аватар из инсты php

Получить аватар из инсты php

Как получить аватар из инстаграм? пробую так, но выдает null

114
wordpress изменить автора записи

wordpress изменить автора записи

Как изменить в wordpress автора записи если пользователь состоит в группе editorКак отобразить у него это поле?

94
В цикле запись HashMap строк из Сканера

В цикле запись HashMap строк из Сканера

Сделать в цикле запись в HashMap строк из Сканера, пока пользователь не введет qКлючем записи будет текущая дата, значение - текст из сканера

127