@rakas

Стоит ли хранить изображения base64 в БД?

Я использую Laravel Backpack админ-панель на сайте, который имеет функционал написания статей. В статьи можно вставлять изображения. Laravel Backpack предоставляет коробочное решение с использованием Summernote. Он по дефолту все загружаемые картинки сохраняет в БД в виде Base64. И дело в том, что изменить подобное поведение без танцев с бубном не получится (если вы предложите решение, буду очень благодарен).

Так вот, есть ли смысл идти по пути наименьшего сопротивления и хранить картинки в LONG TEXT поле БД? (Лонг текст, т.к. кроме изображений в БД хранится форматированный текст статьи).

Ограничение размера картинки - 10 МБ. В среднем имеем картинки 2-4 МБ.
  • Вопрос задан
  • 324 просмотра
Решения вопроса 1
Sanasol
@Sanasol
нельзя просто так взять и загуглить ошибку
Стоит ли хранить изображения base64 в БД?

нет

composer require symfony/dom-crawler

use Symfony\Component\DomCrawler\Crawler;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\File;

$desc = $request->input('some_html'); // POST with html
$dom_desc = new Crawler($desc);
$images = $dom_desc->filterXPath('//img')->extract(array('src')); // extract images
 
foreach ($images as $key => $value) {
    if (strpos($value, 'base64') !== false) { // leave alone not base64 images
        $data = explode(',', $value); // split image mime and body
        $tmp_file = tempnam('/tmp', 'items'); // create tmp file path
        file_put_contents($tmp_file, base64_decode($data[1])); // fill temp file with image
        $path = Storage::putFile('public/items', new File($tmp_file)); // put file to final destination
        $desc = str_replace($value, $path, $desc); // replace src of converted file to fs path
        unlink($tmp_file); // delete temp file
    }
}
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
mayton2019
@mayton2019
Bigdata Engineer
Классические реляционные СУБД (MySQL) плохо приспособлены к хранению бинарных
файлов. Все дело в размере строки. Исторически 1 строка (data_row) в БД не превышала 4-8 килобайт.
Исходя из этого ограничения БД проектируют кеш и алгоритмы когеретности по кешу.
И все работает отлично до тех пор пока вы не начинаете миксовать крупные файлы и строку БД.
В этом случае мехнизм кеширования БД ломается и БД вынуждена ходить в disk (tablespace)
который по total cost of ownership всегда стоит дороже чем обычный диск, и тем более дороже
чем хранилище AWS/MS-Blob/GDrive. Дороже будет стоить бэкап базы данных которая на 95%
к примеру состоит из JPG картинок вместо реляционных данных. Такова специфика дискового
пространства почти любой БД. Не удивляйтесь если облачный биллинг вам выкатит счет
по которому JPG картинки будут стоить как крипта. Дороже будет сетевой траф для публикации картинки
ведь вам надо сделать сначала трансфер этих мегабайтов с хоста MySQL в Node/Tomcat/Apache
и лишь только потом сделать еще один трансфер с веб хостинга к клиенту. Трафик - 2x.

Поэтому имеет смысл толстые картинки положить в обычный диск под веб сервером Apache
или пошарить хранилище через web-endpoint. В этом случае биллинг за хостинг картинок
для вас станет хотя-бы разумным. А в реляционной базе хранить тольк URL на этот диск.
Ответ написан
saboteur_kiev
@saboteur_kiev
software engineer
В общем случае - нет.
В конкретных случаях - ну если много маленьких иконок, то можно использовать такой вариант. Или svg текстом можно так хранить.
base64 кодирует все триолями, поэтому любой файл увеличивается на ~30%, если что то уж хотя бы в бинарных blob можно пробовать. А так - просто в виде файлов или специализированная база типа s3 предпочтительнее
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы