Вступление
Пользователи не только потребляют данные, они также производят данные и загружают их. Они могут отправлять данные через приложения, такие как мессенджеры или электронная почта, определенным получателям или загружать файлы в социальные сети и платформы потоковой передачи данных, такие как Facebook или YouTube.
При этом почти каждый интерактивный веб-сайт сегодня поддерживает загрузку файлов.
Библиотеки загрузки файлов
В NPM доступно несколько библиотек узлов, которые могут упростить процесс проверки и загрузки файлов на сервер. Среди них наиболее популярными в наши дни являются Multer , Formidable и Multiparty .
Все они имеют стабильные версии и поддерживаются онлайн-сообществом разработчиков с открытым исходным кодом.
Что такое Мультер?
Multer - популярное промежуточное ПО для Node.js, используемое для
обработки запросов multipart/form-data
Он использует
busboy для анализа любых данных,
полученных через HTML-форму. Это значительно повышает его
производительность, поскольку модуль busboy не имеет себе равных, когда
дело доходит до анализа данных формы.
Multer предоставляет нам контроль и гибкость при обработке
multipart/form-data
- мы получаем подробную информацию о каждом
загруженном файле, возможность добавить собственный механизм хранения,
проверку файлов в соответствии с нашими потребностями, возможность
устанавливать ограничения на загружаемые файлы, и т.п.
Настройка проекта
Поскольку мы не будем хранить наши изображения в базе данных, а будем
хранить их в простой папке для краткости и простоты, давайте создадим
еще одну папку в папке нашего проекта и назовем ее, скажем, uploads
.
Теперь установим Express:
$ npm i express
И, наконец, установим Multer:
$ npm i multer
Реализация проекта
На этом этапе мы готовы написать код, начиная с HTML-форм, которые мы будем использовать для сбора информации.
Начнем с формы для загрузки одного файла:
<form method="POST" action="/upload-profile-pic" enctype="multipart/form-data">
<div>
<label>Select your profile picture:</label>
<input type="file" name="profile_pic" />
</div>
<div>
<input type="submit" name="btn_upload_profile_pic" value="Upload" />
</div>
</form>
А затем с помощью формы, которая позволяет нам загружать несколько файлов:
<form method="POST" action="/upload-multiple-images" enctype="multipart/form-data">
<div>
<label>Select multiple images:</label>
<input type="file" name="multiple_images" multiple />
</div>
<div>
<input type="submit" name="btn_upload_multiple_images" value="Upload" />
</div>
</form>
Вы можете разместить эти формы на разных страницах или на одной. В этом руководстве они расположены один за другим:
{.ezlazyload}
Формы HTML довольно просты, они принимают данные multipart/form-data
и
направляют соответствующие функции, которые обрабатывают их запросы.
Экспресс-заявка
Когда наши формы готовы, мы можем работать над реальной логикой загрузки и проверки файлов через Express.
Давайте создадим файл с именем app.js
в корне проекта и начнем с
импорта необходимых модулей:
const express = require('express');
const multer = require('multer');
const path = require('path');
Теперь давайте создадим наше приложение Express:
const app = express();
И наконец, давайте настроим порт, на котором он будет работать:
const port = process.env.PORT || 3000;
public
каталог от нашей корневой папки содержит статические файлы ,
которые мы хотим служить, так что давайте установить его в качестве
каталога статического использования express.static
:
app.use(express.static(__dirname + '/public'));
На этом этапе давайте определим место хранения наших изображений:
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, 'uploads/');
},
// By default, multer removes file extensions so let's add them back
filename: function(req, file, cb) {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
}
});
И, наконец, запустим приложение, используя порт, который мы установили ранее:
app.listen(port, () => console.log(`Listening on port ${port}...`));
Проверка и загрузка файлов
По фундаментальным соображениям безопасности мы хотим проверять файлы
перед их загрузкой на наши серверы. Давайте отредактируем app.js
и
добавим обе функции:
app.post('/upload-profile-pic', (req, res) => {
// 'profile_pic' is the name of our file input field in the HTML form
let upload = multer({ storage: storage, fileFilter: helpers.imageFilter }).single('profile_pic');
upload(req, res, function(err) {
// req.file contains information of uploaded file
// req.body contains information of text fields, if there were any
if (req.fileValidationError) {
return res.send(req.fileValidationError);
}
else if (!req.file) {
return res.send('Please select an image to upload');
}
else if (err instanceof multer.MulterError) {
return res.send(err);
}
else if (err) {
return res.send(err);
}
// Display uploaded image for user validation
res.send(`You have uploaded this image: <hr/><img src="${req.file.path}" width="500"><hr /><a href="./">Upload another image</a>`);
});
});
Здесь мы приняли HTTP- запрос POST, в котором содержится информация об
изображении. Функция, которая на самом деле заботится о функциональности
загрузки, - это multer().single()
.
Вы могли заметить fileFilter: helpers.imageFilter
но мы еще не создали
/ импортировали файл helpers
Итак, давайте создадим новый файл в
каталоге нашего проекта и helpers.js
его helpers.js. Здесь мы напишем
код, который будет использоваться для проверки, является ли отправленный
файл изображением или нет.
const imageFilter = function(req, file, cb) {
// Accept images only
if (!file.originalname.match(/\.(jpg|JPG|jpeg|JPEG|png|PNG|gif|GIF)$/)) {
req.fileValidationError = 'Only image files are allowed!';
return cb(new Error('Only image files are allowed!'), false);
}
cb(null, true);
};
exports.imageFilter = imageFilter;
Конечно, чтобы использовать этот модуль, нам нужно будет импортировать
его в app.js
файла app.js:
const helpers = require('./helpers');
Теперь мы можем запустить наше приложение и убедиться, что оно работает правильно:
{.ezlazyload}
Загрузка нескольких файлов
Загрузка нескольких файлов по сути аналогична загрузке одного файла.
Хотя вместо функции multer().single()
мы используем multer().array()
:
app.post('/upload-multiple-images', (req, res) => {
// 10 is the limit I've defined for number of uploaded files at once
// 'multiple_images' is the name of our file input field
let upload = multer({ storage: storage, fileFilter: helpers.imageFilter }).array('multiple_images', 10);
upload(req, res, function(err) {
if (req.fileValidationError) {
return res.send(req.fileValidationError);
}
else if (...) // The same as when uploading single images
let result = "You have uploaded these images: <hr />";
const files = req.files;
let index, len;
// Loop through all the uploaded images and display them on frontend
for (index = 0, len = files.length; index < len; ++index) {
result += `<img src="${files[index].path}" width="300" style="margin-right: 20px;">`;
}
result += '<hr/><a href="./">Upload more images</a>';
res.send(result);
});
});
А теперь, чтобы проверить, все ли работает правильно:
{.ezlazyload}
Заключение
Пользователи не только потребляют данные, они производят данные, и во многих случаях им необходимо загрузить их на веб-сервер. Они могут отправлять данные через приложения, такие как мессенджеры или электронная почта, определенным получателям, или они могут загружать файлы в социальные сети и платформы потоковой передачи данных, такие как Facebook или YouTube.
В этой статье мы использовали Express.js и библиотеку Multer для обработки основных функций загрузки файлов в простом веб-приложении.