[Из песочницы] Node.js + JQuery Ajax. Загрузка файлов на сервер

Введение В данные статье я хочу вам рассказать о моем способе загрузки файлов на сервер Node.js с помощью JQuery Ajax. Да, я понимаю что есть уже и другие решения, например JQuery File Upload, но все таки иногда хочется сделать что-то уже существующее, для того чтобы понять как это все устроено. Данное решение является учебным примером, все замечания по поводу кода или предложения по его улучшению оставляйте в комментариях.Что будем использовать Bootstrap JQuery Модуль для Node.js Multiparty Отправка файла с помощью Ajax Конечно здесь наверное самый жуткий код. Все элементы на странице создаются вручную. За загрузку отвечает класс JSUploader вот один из его методов uploadFile: this.uploadFile = function (index) { //baseClass это this var file = baseClass.allFiles[index];

//Создаем объек FormData var data = new FormData (); //Добавлем туда файл data.append ('uploadFile', file.file);

//отсылаем с попощью Ajax $.ajax ({ url: '/', data: data, cache: false, contentType: false, processData: false, type: 'POST', success: function (response) { var message = file.element.find ('td.message'); if (response.status == 'ok') { message.html (response.text); file.element.find ('button.uploadButton').remove (); } else { message.html (response.errors); } }, xhr: function () { var xhr = $.ajaxSettings.xhr ();

if (xhr.upload) { console.log ('xhr upload');

xhr.upload.onprogress = function (e) { file.progressDone = e.position || e.loaded; file.progressTotal = e.totalSize || e.total; //обновляем прогресс для файла baseClass.updateFileProgress (index, file.progressDone, file.progressTotal, file.element); //обновляем общий прогресс baseClass.totalProgressUpdated (); }; }

return xhr; } }); }; Обработка загрузки файлов Для загрузки файлов на сервер нам понадобиться модуль multiparty, который можно установить с помощью команды в консоле: npm install multipartyДалее код который обрабатывает post и get запросы начальной страницы. Здесь мы отображаем форму загрузки и обрабатываем post запрос на загрузку файла.При окончание загрузки мы сообщаем клиенту что все хорошо или если есть ошибки, то отправить их. Единственная проблема по моему мнению — это то, что в данном коде сервер не может сразу завершить загрузку и сообщить об ошибки, для этого приходиться ждать полной загрузки файла. Решение проблемы возможно если мы как-нибудь вызовем сигнал onclose у формы, но к сожалению пока решения я не нашел.

var express = require ('express'), router = express.Router (), fs = require («fs»), multiparty = require ('multiparty');

//здесь выводим форму для загрузки router.get ('/', function (req, res) { res.render ('index', { title: 'Node.js File Uploads' }); });

//здесь происходит сама загрузка router.post ('/', function (req, res, next) { // создаем форму var form = new multiparty.Form (); //здесь будет храниться путь с загружаемому файлу, его тип и размер var uploadFile = {uploadPath: '', type: '', size: 0}; //максимальный размер файла var maxSize = 2×1024 * 1024; //2MB //поддерживаемые типы (в данном случае это картинки формата jpeg, jpg и png) var supportMimeTypes = ['image/jpg', 'image/jpeg', 'image/png']; //массив с ошибками произошедшими в ходе загрузки файла var errors = [];

//если произошла ошибка form.on ('error', function (err){ if (fs.existsSync (uploadFile.path)) { //если загружаемый файл существует удаляем его fs.unlinkSync (uploadFile.path); console.log ('error'); } });

form.on ('close', function () { //если нет ошибок и все хорошо if (errors.length == 0) { //сообщаем что все хорошо res.send ({status: 'ok', text: 'Success'}); } else { if (fs.existsSync (uploadFile.path)) { //если загружаемый файл существует удаляем его fs.unlinkSync (uploadFile.path); } //сообщаем что все плохо и какие произошли ошибки res.send ({status: 'bad', errors: errors}); } });

// при поступление файла form.on ('part', function (part) { //читаем его размер в байтах uploadFile.size = part.byteCount; //читаем его тип uploadFile.type = part.headers['content-type']; //путь для сохранения файла uploadFile.path = './files/' + part.filename;

//проверяем размер файла, он не должен быть больше максимального размера if (uploadFile.size > maxSize) { errors.push ('File size is ' + uploadFile.size + '. Limit is' + (maxSize / 1024 / 1024) + 'MB.'); }

//проверяем является ли тип поддерживаемым if (supportMimeTypes.indexOf (uploadFile.type) == -1) { errors.push ('Unsupported mimetype ' + uploadFile.type); }

//если нет ошибок то создаем поток для записи файла if (errors.length == 0) { var out = fs.createWriteStream (uploadFile.path); part.pipe (out); } else { //пропускаем //вообще здесь нужно как-то остановить загрузку и перейти к onclose part.resume (); } });

// парсим форму form.parse (req); }); Ссылки

© Habrahabr.ru