TL; DR: в этой статье содержится руководство по загрузке нескольких файлов в AWS (s3) перед сохранением URL-адреса загруженного актива в вашей базе данных в одном запросе.

В первом посте этой серии от Otoloye Oyeniran мы выполнили настройку приложения с необходимыми базовыми файлами, а также продемонстрировали, как загрузить один актив в AWS с помощью промежуточного программного обеспечения Multer перед вашим контроллером. выполняет операцию CRUD.

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

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

Первой остановкой для нас будет выведение функции загрузки в отдельный модуль.

Здесь нам нужны три основных пакета aws-sdk, модуль fs узла и dotenv для анализа переменных среды, которые мы хотим скрыть от общего просмотра / доступа.

В строках 6–13 upload-to-s3.js мы реализуем базовую конфигурацию для aws. Эта конфигурация была рассмотрена в Части 1 этой серии.

Теперь мы заставляем функцию uploadToS3 возвращать Promise. Мне особенно нравится создавать таким образом зависящие от времени функции, главным образом потому, что в момент вызова функции вы можете вызвать .then и выполнить любое необходимое действие. Это нам хорошо подходит, потому что после того, как мы вызываем эту функцию, и происходит наша загрузка и возвращается URL-адрес ресурса на s3, then мы можем продолжить и сохранить вместе с другими полями в DB.

Я очень люблю абстракции. Это гарантирует, что код будет модульным и более понятным. И по этой причине я абстрагировал checkMulterParams функцию от upload-to-s3. Эта функция проверяет тип и количество файлов, которые нам нужно загрузить, и выполняет с ними необходимые операции. Давайте взглянем на этот файл.

ПО промежуточного слоя multer принимает ряд параметров конфигурации, когда вы хотите загрузить один файл, или массив файлов, или объект, ключи которого указывают на каждый файл.

.single(fieldname): Принимает один файл с именем fieldname. Один файл будет сохранен в объекте req.file, когда промежуточное ПО будет добавлено к вашему маршруту.

.array(fieldname[maxCount]: Принимает массив файлов, каждый из которых имеет имя fieldname.. Обратите внимание, что fieldname может быть любым именем / ключом, которым вы хотите, чтобы файл находился в БД. Запрос может быть ошибочным, если загружено более maxCount файлов. Массив файлов будет храниться в req.files.

.fields(fields): Принимает набор файлов, указанных в fields. Это объект с массивами файлов, которые будут храниться в req.files. Каждый файл в массиве должен быть объектом, и поэтому может показаться, что когда все разбито, все сводится к загрузке нескольких отдельных файлов, а структура данных для одного файла представляет собой объект.

Вооружившись этой информацией, мы могли бы сделать .fields типом по умолчанию. В конце концов, как объяснялось в последнем абзаце, все заканчивается загрузкой одного файла.

Функция checkMulterParams многофункциональна. Он проверяет, указали ли мы array, fields или single на промежуточном программном обеспечении multer, и логика обрабатывает разбивку данных, которые должны быть переданы функции uploadToS3.

Мы возвращаем массив объектов из checkMulterParams независимо от типа переданных данных. Этот этап можно назвать нормализацией данных. Это полезно, потому что заставляет нашу uploadToS3 функцию беспокоиться только о загрузке, а не о структуре данных.

Также обратите внимание, что мы заставляем функцию uploadToS3 принимать объект в качестве аргумента. Это гарантирует, что функция принимает только один параметр, который мы можем заполнить как можно большим количеством пар ключ-значение. Это помогает гарантировать, что нам не придется беспокоиться о позиционных параметрах в месте вызова функции.

Наконец, мы готовы использовать функцию uploadToS3 в нашем контроллере. Поехали:

Во-первых, у нас есть сервер

Затем у нас есть файл пользовательских маршрутов. Вы видите, что мы указываем fields в промежуточном программном обеспечении multer следующим образом:

Модель пользователя показана ниже. Он содержит возможные поля, которые мы определили для нашего пользователя.

Наконец, пользовательский контроллер выглядит так, как показано ниже.

Вы заметите, что у нас есть три условных оператора. Каждый из них для случаев, в которых указано одно, либо другое, либо оба поля, для которых необходимо загрузить ресурсы. Мы делаем это, чтобы не вызывать дорогостоящий uploadToS3 метод, если он не является абсолютно необходимым. Также вы видите, что мы используем Promise.all. Это удобный метод Promise, который принимает массив обещаний и не возвращает результат до тех пор, пока обещания не будут выполнены (здесь я использую завершено, потому что каждое отдельное обещание может быть выполнено или отклонено).

Мы также назначаем объект req.body переменной userRequestObject и присваиваем значения urls, которые указывают на наши активы, только когда они у нас есть. Пока мы не получим эти URL-адреса, мы сможем создать нового пользователя, как показано в строке 43 файла users-controller.js.

Запустите почтальона в этот момент и перейдите к маршруту /signup. Если все пойдет хорошо, вы должны увидеть сообщение: user created успешно`

Я не особо разбирался с возможностью невыполнения какого-либо из обещаний здесь с помощью .catch, и это то, на что вам нужно обратить внимание, иначе неудача где-то может привести к нежелательным осложнениям.

Путешествие было долгим, но надеюсь, оно того стоило.

Полный исходный код можно найти на GITHUB здесь.

Не стесняйтесь оставлять свои отзывы и вопросы ниже.