Téléchargement de fichiers avec Express 4.0: fichiers req non définis

239

J'essaie d'obtenir un mécanisme de téléchargement de fichiers simple fonctionnant avec Express 4.0 mais je continue à undefinedchercher req.filesdans le app.postcorps. Voici le code pertinent:

var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//...
app.use(bodyParser({ uploadDir: path.join(__dirname, 'files'), keepExtensions: true })); 
app.use(methodOverride()); 
//...
app.post('/fileupload', function (req, res) {
  console.log(req.files); 
  res.send('ok'); 
}); 

.. et le code Pug qui l'accompagne:

form(name="uploader", action="/fileupload", method="post", enctype="multipart/form-data")
    input(type="file", name="file", id="file")
    input(type="submit", value="Upload")

Solution
Grâce à la réponse de mscdex ci-dessous, je suis passé à l'utilisation busboyau lieu de bodyParser:

var fs = require('fs');
var busboy = require('connect-busboy');
//...
app.use(busboy()); 
//...
app.post('/fileupload', function(req, res) {
    var fstream;
    req.pipe(req.busboy);
    req.busboy.on('file', function (fieldname, file, filename) {
        console.log("Uploading: " + filename); 
        fstream = fs.createWriteStream(__dirname + '/files/' + filename);
        file.pipe(fstream);
        fstream.on('close', function () {
            res.redirect('back');
        });
    });
});
safwanc
la source
1
comment cela fonctionne-t-il avec plusieurs fichiers?
chovy
@chovy cela devrait fonctionner très bien avec plusieurs fichiers
mscdex
2
ithink il est possible de faire app.post ('/ fileupload', busboy (), function (req, res) {
Shimon Doodkin
Bonne solution Je voulais juste noter que vous devez créer un ./files/répertoire dans le répertoire personnel de votre application, sinon vous obtiendrez une erreur après le téléchargement.
sauce
Comment sont gérés les fichiers temporaires? Busboy les supprime-t-il automatiquement? Je ne vois simplement aucun fichier temporaire supprimé avant l'enregistrement sur le disque.
ed-ta

Réponses:

210

Le body-parsermodule ne gère que les soumissions de formulaires JSON et urlencodées, pas multiparties (ce qui serait le cas si vous téléchargez des fichiers).

Pour le multipart, vous devez utiliser quelque chose comme connect-busboyou multerou connect-multiparty(multiparty / formidable est ce qui était à l'origine utilisé dans le middleware express bodyParser). Aussi FWIW, je travaille sur une couche de niveau encore plus élevé au-dessus de busboy appelé reformed. Il est livré avec un middleware Express et peut également être utilisé séparément.

mscdex
la source
4
Merci, ça a marché. Bien que je devais utiliser connect-busboyau lieu de juste busboy. Mise à jour de mon message d'origine avec la solution.
safwanc
4
Merci mon pote! Je trouve la connect-multipartymeilleure option parmi celles-ci!
neciu
Est reformedencore en développement? Votre dernier commit sur github date de 2014 ... Au fait, à votre avis, quel est le meilleur module pour gérer les données de formulaires en plusieurs parties? Par "meilleur", je veux dire le meilleur supporté et celui qui fonctionne mieux (moins de bugs), avec plus de fonctionnalités et avec un avenir plus long ... J'ai choisi multerparce qu'il semblait le mieux supporté, mais je pense toujours qu'il devrait être plus supporté.
nbro
[EDIT: ça va, je viens de voir la réponse ci-dessous.] Est-ce que multipart avec express 3.0, puis cassé en 4.0? je demande parce que ce tutoriel utilise 3.4.8 et peut télécharger des fichiers sans avoir besoin de middleware supplémentaire blog.robertonodi.me/simple-image-upload-with-express
thetrystero
@thetrystero Le dépôt github pour cet exemple particulier auquel vous avez lié a en fait les dépendances archivées dans le dépôt. Si vous fouillez dans ces dépendances, vous verrez qu'Express 3.x est inclus, ainsi que Connect 2.x (qui contenait toujours un module multipartie). C'est pourquoi la gestion en plusieurs parties fonctionnait "hors de la boîte".
mscdex
31

Voici ce que j'ai trouvé sur Google:

var fileupload = require("express-fileupload");
app.use(fileupload());

Ce qui est un mécanisme assez simple pour les téléchargements

app.post("/upload", function(req, res)
{
    var file;

    if(!req.files)
    {
        res.send("File was not found");
        return;
    }

    file = req.files.FormFieldName;  // here is the field name of the form

    res.send("File Uploaded");


});
Anton Stafeyev
la source
trop lent pour les gros fichiers
Eduardo
3
Tu n'as pas utilisé fileupload?
BrandonFlynn-NB
5
Pour que la réponse ci-dessus fonctionne, vous devez ajouter ces deux lignes dans votre mainapp.js const fileUpload = require('express-fileupload') app.use(fileUpload())
abhishake
11

Il ressemble a body-parser fait support des fichiers de téléchargement des express 3, mais le soutien a été abandonné pour Express 4 quand il ne comprenait plus se connecter en tant que dépendance

Après avoir parcouru certains des modules de la réponse de mscdex, j'ai trouvé que express-busboyc'était une bien meilleure alternative et la chose la plus proche d'un remplacement sans rendez-vous . Les seules différences que j'ai remarquées concernaient les propriétés du fichier téléchargé.

console.log(req.files)en utilisant l' analyseur de corps (Express 3), affichez un objet qui ressemblait à ceci:

{ file: 
   { fieldName: 'file',
     originalFilename: '360px-Cute_Monkey_cropped.jpg',
     name: '360px-Cute_Monkey_cropped.jpg'
     path: 'uploads/6323-16v7rc.jpg',
     type: 'image/jpeg',
     headers: 
      { 'content-disposition': 'form-data; name="file"; filename="360px-Cute_Monkey_cropped.jpg"',
        'content-type': 'image/jpeg' },
     ws: 
      WriteStream { /* ... */ },
     size: 48614 } }

par rapport à l' console.log(req.files)utilisation de express-busboy (Express 4):

{ file: 
   { field: 'file',
     filename: '360px-Cute_Monkey_cropped.jpg',
     file: 'uploads/9749a8b6-f9cc-40a9-86f1-337a46e16e44/file/360px-Cute_Monkey_cropped.jpg',
     mimetype: 'image/jpeg',
     encoding: '7bit',
     truncated: false
     uuid: '9749a8b6-f9cc-40a9-86f1-337a46e16e44' } }
HPierce
la source
8

1) Assurez-vous que votre fichier est réellement envoyé du côté client. Par exemple, vous pouvez le vérifier dans Chrome Console: capture d'écran

2) Voici l'exemple de base du backend NodeJS:

const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();

app.use(fileUpload()); // Don't forget this line!

app.post('/upload', function(req, res) {
   console.log(req.files);
   res.send('UPLOADED!!!');
});
Dmitry Kulahin
la source
7

multer est un middleware qui gère les «multipart / form-data» et qui, comme par magie, met à disposition les fichiers téléchargés et les données de formulaire dans request sous request.files et request.body.

installer multer: - npm install multer --save

dans le fichier .html: -

<form method="post" enctype="multipart/form-data" action="/upload">
    <input type="hidden" name="msgtype" value="2"/>
    <input type="file" name="avatar" />
    <input type="submit" value="Upload" />
</form>

dans le fichier .js: -

var express = require('express');
var multer = require('multer');
var app = express();
var server = require('http').createServer(app);
var port = process.env.PORT || 3000;
var upload = multer({ dest: 'uploads/' });

app.use(function (req, res, next) {
  console.log(req.files); // JSON Object
  next();
});

server.listen(port, function () {
  console.log('Server successfully running at:-', port);
});

app.get('/', function(req, res) {
  res.sendFile(__dirname + '/public/file-upload.html');
})

app.post('/upload', upload.single('avatar'),  function(req, res) {
  console.log(req.files); // JSON Object
});

J'espère que cela t'aides!

Parth Raval
la source
2

Veuillez utiliser le code ci-dessous

app.use(fileUpload());
Gaurav kumar
la source
var fileupload = require ("express-fileupload"); app.use (fileupload ());
Saurabh Agarwal
0

PROBLÈME RÉSOLU !!!!!!!

Il s'avère que la storagefonction n'a PAS fonctionné une seule fois. parce que je devais inclure app.use(upload)commeupload = multer({storage}).single('file');

 let storage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, './storage')
          },
          filename: function (req, file, cb) {
            console.log(file) // this didn't print anything out so i assumed it was never excuted
            cb(null, file.fieldname + '-' + Date.now())
          }
    });

    const upload = multer({storage}).single('file');
Sharl Sherif
la source
-1

express-fileupload ressemble au seul middleware qui fonctionne encore de nos jours.

Avec le même exemple, multeret connect-multipartydonne une valeur non définie de req.file ou req.files , maisexpress-fileupload fonctionne.

Et il y a beaucoup de questions et de problèmes soulevés au sujet de la valeur vide de req.file / req.files .

trd
la source