Firebase потрясающая. Как написано в предыдущей статье JSMonday, он позволяет нам писать бессерверные приложения, аутентифицировать пользователей и многое другое.

Firebase также предлагает услугу Firebase Storage, которая чем-то похожа на AWS S3. Вы можете создать ведро, а затем вставить в него любой файл. Обычно он используется для хранения изображений, но здесь возникает проблема: что, если пользователь загружает невероятно тяжелое изображение? Вы можете изменить его размер!
Давайте посмотрим, как это сделать с помощью функций Firebase.

Прежде всего, давайте инициализируем новый проект Firebase Functions.
Затем давайте установим пару пакетов npm:

Как видите, мы устанавливаем эти три пакета:

  • @google-cloud/storage позволяет получать изображения из Firebase Storage.
  • fs-extra, который включает в себя модуль fs по умолчанию для Node.js и предоставляет его функции с помощью обещаний.
  • sharp, потрясающая и высокопроизводительная библиотека для работы с изображениями для Node.js

Теперь мы готовы написать наш инструмент для изменения размера изображения!
Давайте перейдем к нашему functions/index.js файлу и начнем импортировать необходимые нам зависимости:

Большой! Теперь мы можем начать писать наш обработчик функции:

Как видите, мы сообщаем нашей функции Firebase, что нам нужно как минимум 2 ГБ памяти и максимум 120 секунд времени для выполнения нашей функции. Мы также заявляем, что нам нужно активировать эту функцию после того, как изображение будет загружено в нашу корзину (storage.object().onFinalize).

Напишем функцию handler:

Нам нужно получить кучу информации из нашего аргумента object (который на самом деле является объектом, описывающим, куда было загружено наше изображение):

  • Bucket: сегмент, в который мы загрузили изображение.
  • Путь к файлу: путь к файлу внутри нашего сегмента.
  • Имя файла: имя загруженного файла.
  • Bucket Directory: имя каталога, в который мы загрузили наше изображение.

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

Теперь возникает проблема: наша функция запускается каждый раз, когда в нашем Bucket создается новый файл ... но на самом деле мы создаем новое изображение с измененным размером, так как же нам избежать бесконечного цикла изменения размера?

Мы зададим имя типа myImage@s_1920.jpg для нашего изображения с измененным размером (где s_ означает «размер»), чтобы мы могли проверить, является ли вновь созданное изображение результатом изменения размера или нет.
image само по себе является изображением с измененным размером, мы выйдем из нашей функции.

Теперь нам просто нужно скачать только что созданный образ. Мы загрузим его по ранее созданному пути временного файла:

Теперь мы готовы приступить к изменению размера! Допустим, нам нужно создать три разных размера: 1920 пикселей, 720 пикселей, 100 пикселей. Давайте превратим эти значения в массив:

Теперь нам нужно запустить средство изменения размера, поэтому мы создадим обещание для каждого размера внутри нашего массива:

Как видите, процесс довольно простой:

  • Получите расширение изображения.
  • Получите исходное имя изображения.
  • Создайте окончательное имя изображения.
  • Получите свой путь.
  • Теперь давайте запустим sharp и изменим размер изображения, а затем сохраним его в файл.
  • И последнее, но не менее важное: загрузите изображение в исходную корзину с новым именем файла.

Теперь нам просто нужно выполнить эти три обещания ... но мы не хотим запускать их последовательно, это может занять слишком много времени! Поэтому мы будем использовать Promise.all, чтобы запускать их одновременно:

Готово!
Давайте развернем функцию и протестируем ее, загрузив файл в Firebase Storage:

Теперь мы готовы запустить наше средство изменения размера!
В JSMonday мы фактически используем приведенный выше код для изменения размера наших изображений:



Не стесняйтесь повторно использовать приведенный выше код для изменения размера изображения!