Использовать Multer в Express Route? (Используя MEANJS)

Я использую Multer для загрузки изображений в Express 4. Однако все примеры показывают, что Multer определяется в файле Express как ПО промежуточного слоя. Я хотел бы фактически определить некоторые из поведений Multer в самой маршрутизации моего приложения. Это возможно? Конечный результат, который мне нужен, заключается в том, чтобы моя функция маршрута распознавала, когда загрузка завершена, прежде чем она отправит ответ сервера в браузер, чтобы изображение могло отображаться пользователю (сейчас я получаю только частичное изображение, потому что файл еще не закончил загрузку).

АКТУАЛЬНЫЙ, РАБОЧИЙ КОД

express.js

// Require Multer as module dependency.
var multer = require('multer');

// Using Multer for file uploads.
app.use(multer({
    dest: './public/profile/img/',
    limits: {
        fieldNameSize: 50,
        files: 1,
        fields: 5,
        fileSize: 1024 * 1024
    },
    rename: function(fieldname, filename) {
        return filename;
    },
    onFileUploadStart: function(file) {
        if(file.mimetype !== 'image/jpg' && file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png') {
            return false;
        }
    }
}));

server_routes.js

app.route('/users/image').post(server_controller_file.imageUpload);

server_controller_file.js

exports.imageUpload = function(req, res) {
// Check to make sure req.files contains a file, mimetypes match, etc., then send appropriate server response.
};

В идеале мой файл server_controller_file.js должен содержать некоторые проверки, чтобы убедиться, что загрузка файла завершена, например. (примечание: это гипотетический/желательный, а не реальный рабочий код)...

var multer = require('multer');
exports.imageUpload = function(req, res) {
    multer({
        onFileUploadComplete: function(file) {
            res.send();
        }
    });
}

Опять же, прямо сейчас асинхронный характер узла заставляет браузер думать, что загрузка завершена, как только он получает успешный ответ, поэтому, когда я обновляю URL-адрес для отображения изображения, оно отображается только частично. Спасибо за помощь!


person aikorei    schedule 05.01.2015    source источник
comment
Можете ли вы получить file.path в функции onFileUploadComplete?   -  person Ryan Yiada    schedule 06.01.2015
comment
Поскольку multer работает как промежуточное ПО, я думаю, что оно не будет работать в вашем server_controller_file. Поэтому вы не знаете, когда он завершил загрузку файла. См. этот пример: codeforgeek.com/2014/11/file-uploads. -использование-узла-js   -  person Ryan Yiada    schedule 06.01.2015
comment
@RyanYiada Я могу получить доступ к file.path в функции onFileUploadComplete, но он по-прежнему не взаимодействует с моим маршрутизатором. Статья, на которую вы ссылаетесь, была хороша - в ней есть переменная «сделано», которая относится как к промежуточному программному обеспечению, так и к маршрутизатору, но поскольку мое промежуточное программное обеспечение и маршрутизатор находятся в отдельных файлах, мои переменные промежуточного программного обеспечения выходят за рамки для маршрутизатора.   -  person aikorei    schedule 06.01.2015
comment
@aikorei, express.js был основным файлом сервера, верно?   -  person sankar muniyappa    schedule 07.04.2017
comment
@shankarmsr нет, есть отдельный файл server.js, который запускает все и включает файл express.js.   -  person aikorei    schedule 09.04.2017


Ответы (3)


На самом деле вы можете делать то, что хотите, с помощью другого метода:

var express = require('express');
var multer  = require('multer');
var upload = multer({ dest: './uploads/'});
var app = express();

app.get('/', function(req, res){
  res.send('hello world');
});

// accept one file where the name of the form field is named photho
app.post('/', upload.single('photho'), function(req, res){
    console.log(req.body); // form fields
    console.log(req.file); // form files
    res.status(204).end();
});

app.listen(3000);

person Aymen Mouelhi    schedule 19.03.2015
comment
Это лучший подход по сравнению с решением, отмеченным как ответ. он оптимизирует промежуточное ПО для каждого маршрута. Если вы соедините несколько промежуточных программ вместе, вы обнаружите, что экспресс использует потоки, но это не полностью работает с промежуточными программами. События не передаются между промежуточным ПО. Если вы используете два экспресс-промежуточных ПО в цепочке, и каждое из них пытается перехватить все потоковые события и вызывает next(), когда все события завершены, второе промежуточное ПО больше не будет получать требуемые события. В таком случае вам необходимо оптимизировать промежуточное ПО для каждого маршрута. - person SharpCoder; 15.06.2015
comment
Просто быстрый вопрос, почему он заключен в [ ], это похоже на определение цепочки, а не на использование следующей функции? - person Snymax; 11.07.2015
comment
Ваш ответ не будет работать, если имя папки назначения будет зависеть от параметров req.body, как вы тогда это сделаете??? - person Sudhanshu Gaur; 06.09.2015
comment
Что делать, если я хочу загрузить через вызов API отдыха. Что я должен передать функции single()? - person Bagusflyer; 05.02.2016
comment
Я пытаюсь сделать именно то, что упомянул @SudhanshuGaur. Я использую multer для обработки загрузки изображения как части формы, но мне нужно переименовать изображение в значение другого ввода в форме. Не удается передать новое имя файла в multer после заполнения переменной req.body. - person Meelah; 08.03.2016

Хорошо, на самом деле я только что записал необработанные данные. Если вы установите inMemory в true, он отправляет необработанные данные в req.files.file.buffer. Вот окончательное рабочее решение:

express.js

// Using Multer for file uploads.
app.use(multer({
    dest: './public/profile/img/',
    limits: {
        fieldNameSize: 50,
        files: 1,
        fields: 5,
        fileSize: 1024 * 1024
    },
    rename: function(fieldname, filename) {
        return filename;
    },
    onFileUploadStart: function(file) {
        console.log('Starting file upload process.');
        if(file.mimetype !== 'image/jpg' && file.mimetype !== 'image/jpeg' && file.mimetype !== 'image/png') {
            return false;
        }
    },
    inMemory: true //This is important. It's what populates the buffer.
}));

server_controller_file.js

exports.imageUpload = function(req, res) {
    var file = req.files.file,
        path = './public/profile/img/';

    // Logic for handling missing file, wrong mimetype, no buffer, etc.

    var buffer = file.buffer, //Note: buffer only populates if you set inMemory: true.
        fileName = file.name;
    var stream = fs.createWriteStream(path + fileName);
    stream.write(buffer);
    stream.on('error', function(err) {
        console.log('Could not write file to memory.');
        res.status(400).send({
            message: 'Problem saving the file. Please try again.'
        });
    });
    stream.on('finish', function() {
        console.log('File saved successfully.');
        var data = {
            message: 'File saved successfully.'
        };
        res.jsonp(data);
    });
    stream.end();
    console.log('Stream ended.');
};
person aikorei    schedule 06.01.2015

Я нахожу пример для официанта:

exports.upload = function (req, res, next) {
   req.busboy.on('file', function (fieldname, file, filename, encoding, mimetype) {
       // ....
   });

   req.pipe(req.busboy);
};

multer также работает официантом:

 req.pipe(busboy);

https://github.com/expressjs/multer/blob/master/index.js#206

person Ryan Yiada    schedule 06.01.2015
comment
Ты хочешь сказать, что делать то, что я хочу, не получится с Малтером? И что вместо этого я должен использовать Busboy? - person aikorei; 06.01.2015
comment
Это было неясно для меня, пока я не заглянул под капот, но multer — это просто официант, обернутый и реализованный как промежуточное программное обеспечение. Мне нужно было подключиться к событиям busboy на маршруте, поэтому имело смысл просто использовать busboy напрямую. - person eephillip; 11.01.2015
comment
@aikorei, как говорит eephillip, multer - это просто обертка официанта. multer вернется официантом. - person Ryan Yiada; 12.01.2015