web-dev-qa-db-fra.com

Utiliser Multer dans Express Route? (Utilisation de MEANJS)

J'utilise Multer pour télécharger des images dans Express 4. Cependant, les exemples montrent tous que Multer est défini dans le fichier express comme Middleware. J'aimerais définir certains des comportements de Multer dans le routage de mon application elle-même. Est-ce possible? Le résultat final dont j'ai besoin est que ma fonction de routage reconnaisse lorsque le téléchargement est terminé avant d'envoyer la réponse du serveur au navigateur, de sorte qu'une image peut être affichée pour l'utilisateur (pour le moment, je n'affiche qu'une image partielle car le téléchargement du fichier n'est pas encore terminé).

CODE DE TRAVAIL ACTUEL

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.
};

Idéalement, mon server_controller_file.js contiendrait quelques vérifications pour s'assurer que le fichier a terminé le téléchargement, par ex. (note: ceci est un code de travail hypothétique/souhaitable, pas réel) ...

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

Encore une fois, en raison de la nature asynchrone du nœud, le navigateur pense que le téléchargement est terminé dès qu'il reçoit une réponse réussie, donc lorsque je mets à jour l'URL pour afficher l'image, elle ne s'affiche que partiellement. Merci pour l'aide!

13
aikorei

OK, j'ai fini par écrire les données brutes. Si vous définissez inMemory sur true, il envoie les données brutes à req.files.file.buffer. Voici la solution finale et fonctionnelle:

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.');
};
7
aikorei

En fait, vous pouvez faire ce que vous voulez avec une autre méthode:

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);
17
Aymen Mouelhi

Je trouve un exemple pour busboy:

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

   req.pipe(req.busboy);
};

multer est aussi pipe un busboy:

 req.pipe(busboy);

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

2
Ryan Yiada