Summernote — «перезагрузка»

По умолчанию этот редактор, при добавлении изображения в контент, преобразует его в base64. Но при добавлении этого «счастья» в базу данных, даже поля типа TEXT может оказаться недостаточным и со временем БД может увеличится до невероятных размеров.

summernote-1

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

$(document).ready(function () {
    function uploadFiles(files, editor) {
        for (var i = 0; i < files.length; i++) {
            uploadFileOnServer(files[i], editor);
        }
    }

    function uploadFileOnServer(image, editor) {
        var formData = new FormData();
        formData.append('file', image);
        $.ajax({
            data: formData,
            type: "POST",
            url: "URL php-обработчика",
            contentType: false,
            processData: false,
            success: function (url) {
                var image = $('<img>').attr('src', url.fullFilePath);
                editor.summernote("insertNode", image[0]);
            }
        });
    }

    $('#summernote').summernote(
        {
            callbacks: {
                onImageUpload: function (files) {
                    uploadFiles(files, $(this));
                }
            }
        }
    );
});

Ловим каждый файл на стороне сервера и физически перемещаем файл в нужную директорию, возвращаем json ответ, который представляет полный путь к картинке. В зависимости от экосистемы бэкэнда, перемещение файлов может осуществляться как нативными функциями php, так и с использованием функции фреймворка, например, Symfony.

В контексте SF (Symfony Framework), можно воспользоваться пакетом FosJSRouting, для того чтобы обращаться к именам роутов контролера из js кода, примеры использования. Поэтому, после установки и настройки пакета, вместо "URL php-обработчика", куда будет отправляться картинка, мы запишем:

Routing.generate("summernote_upload")

В данном случае, имя роута summernote_upload и далее можно смело писать контролер UploadImageController.php, отвечающий за обработку файлов на сервере:

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;

class UploadImageController extends Controller
{
    /**
     * @Route("/upload", options={"expose"=true}, methods={"POST"}, name="summernote_upload")
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function uploadImageAction(Request $request)
    {
        /** @var $file UploadedFile */
        $file = $request->files->get('file');
        $fileName = md5(uniqid()) . '.' . $file->guessExtension();
        
        // summernote.upload_dir для удобства выносится в параметры
        $relPath = $this->getParameter('summernote.upload_dir');
        
        $absPath = \dirname($this->get('kernel')->getRootDir()) . '/web' . $relPath;
        $fs = new Filesystem();
        if (!$fs->exists($absPath)) {
            $fs->mkdir($absPath);
        }
        $file->move(
            $absPath,
            $fileName
        );
        return new JsonResponse([
            'fullFilePath' => $relPath . $fileName
        ]);
    }
}

Пример на SF показывает как легко можно обработать загрузку файлов для этого редактора. Посредством ajax обращения сразу к нужному контролеру, загрузки файла с использованием Filesystem компонента фреймворка и возвращением результата с последующей вставкой картинки в редактор с указанием полного пути без перезагрузки страницы.

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



Похожие заметки:

Скрипт динамической ширины

Скрипт для равномерного распределения блоков по ширине родительского контейнера. В качестве контейнера может выступать любой блок как определенной ширины, так и неопределенной, вплоть до body. Что умеет?

  • Нарезать блоки на одинаковую ширину в зависимости от заданного количества колонок
  • Генерировать нужное количество колонок
  • Проставлять clearfix после оканчивающей ряд колонки, чтобы вовремя отменить обтекание
  • Удалять лишние clearfix

Открыть здесь

267

Корзина на сайте — часть 1

В статье рассказывается как создать JavaScript корзину на сайте с помощью плагина simpleCart.js

Открыть здесь

559

Корзина на сайте — часть 2

В статье рассказывается как c помощью simpleCart.js делать такие вещи:

  • Выводить товары в том виде, в котором вам надо
  • Обрабатывать переданные товары и возвращать результат
  • Делать дальнейшие операции с заказом

Открыть здесь

1348


Перед тем как писать комментарии, рекомендую ознакомиться:

Markdown синтаксис »

Оформление кода »

Нужна аватарка »

Комментарии


2
avatar

Davi сказал 21-03-2018 в 02:38


А можно как то выводить состояние загрузки?


avatar

Админ

Роман Жариков сказал 21-03-2018 в 09:51


Вполне можно. Достаточно добавить в метод uploadFileOnServer:

$.ajax({
   // ...
   beforeSend: function() {
      // ... делаем что-то
   }
})