web-dev-qa-db-fra.com

Téléchargement de fichier Node / Express

J'utilise les nœuds v0.10.26 et Express v4.2.0 et je suis assez nouveau dans ce domaine. Je frappe ma tête contre mon bureau depuis environ trois heures pour essayer d'obtenir un formulaire de téléchargement de fichier compatible avec node. À ce stade, j'essaie simplement de faire en sorte que req.files ne retourne pas undefined. Ma vue ressemble à ceci

<!DOCTYPE html>
<html>
<head>
  <title>{{ title }}</title>
  <link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
  <h1>{{ title }}</h1>
  <p>Welcome to {{ title }}</p>
  <form method='post' action='upload' enctype="multipart/form-data">
    <input type='file' name='fileUploaded'>
    <input type='submit'>
  </form>
</body>
</html>

Voici mes itinéraires

var express = require('express');
var router = express.Router();


/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

router.post('/upload', function(req, res){
console.log(req.files);
});

module.exports = router;

Et voici mon app.js

var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});



module.exports = app;

J'ai vu quelque part qu'inclure methodOverride() et bodyParser({keepExtensions:true,uploadDir:path}) était supposé aider, mais je ne peux même pas lancer mon serveur si j'ajoute ces lignes.

76
okawei

Problème ExpressJS:

La plupart des middlewares sont supprimés de l'express 4. Consultez: http://www.github.com/senchalabs/connect#middleware Pour les middlewares en plusieurs parties tels que busboy, busboy-connect, formidable, flux, séparé est nécessaire.

Cet exemple fonctionne avec le middleware connect-busboy . créer des dossiers/img et/public.
Utilisez la structure de dossiers:

\ server.js

\ img\"où le contenu est chargé"

\ public\index.html

SERVER.JS

var express = require('express');    //Express Web Server 
var busboy = require('connect-busboy'); //middleware for form/file upload
var path = require('path');     //used for file path
var fs = require('fs-extra');       //File System - for file manipulation

var app = express();
app.use(busboy());
app.use(express.static(path.join(__dirname, 'public')));

/* ========================================================== 
Create a Route (/upload) to handle the Form submission 
(handle POST requests to /upload)
Express v4  Route definition
============================================================ */
app.route('/upload')
    .post(function (req, res, next) {

        var fstream;
        req.pipe(req.busboy);
        req.busboy.on('file', function (fieldname, file, filename) {
            console.log("Uploading: " + filename);

            //Path where image will be uploaded
            fstream = fs.createWriteStream(__dirname + '/img/' + filename);
            file.pipe(fstream);
            fstream.on('close', function () {    
                console.log("Upload Finished of " + filename);              
                res.redirect('back');           //where to go next
            });
        });
    });

var server = app.listen(3030, function() {
    console.log('Listening on port %d', server.address().port);
});

INDEX.HTML

<!DOCTYPE html>
<html lang="en" ng-app="APP">
<head>
    <meta charset="UTF-8">
    <title>angular file upload</title>
</head>

<body>
        <form method='post' action='upload' enctype="multipart/form-data">
        <input type='file' name='fileUploaded'>
        <input type='submit'>
 </body>
</html>

Ce qui suit fonctionnera avec formidable SERVER.JS

var express = require('express');   //Express Web Server 
var bodyParser = require('body-parser'); //connects bodyParsing middleware
var formidable = require('formidable');
var path = require('path');     //used for file path
var fs =require('fs-extra');    //File System-needed for renaming file etc

var app = express();
app.use(express.static(path.join(__dirname, 'public')));

/* ========================================================== 
 bodyParser() required to allow Express to see the uploaded files
============================================================ */
app.use(bodyParser({defer: true}));
 app.route('/upload')
 .post(function (req, res, next) {

  var form = new formidable.IncomingForm();
    //Formidable uploads to operating systems tmp dir by default
    form.uploadDir = "./img";       //set upload directory
    form.keepExtensions = true;     //keep file extension

    form.parse(req, function(err, fields, files) {
        res.writeHead(200, {'content-type': 'text/plain'});
        res.write('received upload:\n\n');
        console.log("form.bytesReceived");
        //TESTING
        console.log("file size: "+JSON.stringify(files.fileUploaded.size));
        console.log("file path: "+JSON.stringify(files.fileUploaded.path));
        console.log("file name: "+JSON.stringify(files.fileUploaded.name));
        console.log("file type: "+JSON.stringify(files.fileUploaded.type));
        console.log("astModifiedDate: "+JSON.stringify(files.fileUploaded.lastModifiedDate));

        //Formidable changes the name of the uploaded file
        //Rename the file to its original name
        fs.rename(files.fileUploaded.path, './img/'+files.fileUploaded.name, function(err) {
        if (err)
            throw err;
          console.log('renamed complete');  
        });
          res.end();
    });
});
var server = app.listen(3030, function() {
console.log('Listening on port %d', server.address().port);
});
84
Mick Cullen

Une autre option consiste à utiliser multer , qui utilise busboy sous le capot, mais est plus simple à configurer.

var multer = require('multer');

Utilisez multer et définissez la destination du téléchargement:

app.use(multer({dest:'./uploads/'}));

Créez un formulaire dans votre vue, enctype='multipart/form-data est requis pour que multer fonctionne:

form(role="form", action="/", method="post", enctype="multipart/form-data")
    div(class="form-group")
        label Upload File
        input(type="file", name="myfile", id="myfile")

Ensuite, dans votre POST, vous pouvez accéder aux données relatives au fichier:

app.post('/', function(req, res) {
  console.dir(req.files);
});

Un tutoriel complet sur ceci peut être trouvé ici .

24
Carasel

Voici une version simplifiée ( du Gist ) de réponse de Mick Cullen - en partie pour prouver que la mise en œuvre de cette méthode n'est pas nécessairement complexe; en partie pour donner une référence rapide à quiconque n'est pas intéressé par la lecture de pages et de pages de code.


Vous devez vous faire utiliser l'application [connect-busboy] :

var busboy = require("connect-busboy");
app.use(busboy());

Cela ne fera rien jusqu'à ce que vous le déclenchiez. Dans l'appel qui gère le téléchargement, procédez comme suit:

app.post("/upload", function(req, res) {
    if(req.busboy) {
        req.busboy.on("file", function(fieldName, fileStream, fileName, encoding, mimeType) {
            //Handle file stream here
        });
        return req.pipe(req.busboy);
    }
    //Something went wrong -- busboy was not loaded
});

Décomposons ceci:

  • Vous vérifiez si req.busboy est défini (le middleware a été chargé correctement)
  • Vous configurez un écouteur "file" sur req.busboy
  • Vous dirigez le contenu de req vers req.busboy

Dans l'écouteur de fichier, il y a quelques éléments intéressants, mais ce qui compte vraiment, c'est le fileStream: il s'agit d'un Readable , qui peut ensuite être écrit dans un fichier, comme vous le feriez habituellement.

Piège: Vous devez gérer ceci en lecture, sinon Express ne répondra jamais à la demande , voir l'API busboy ( fichier section).

21
Niels Abildgaard

Je trouve cela simple et efficace:

app.post('/upload', function(req, res) {
   if (!req.files)
      return res.status(400).send('No files were uploaded.');

   // The name of the input field (i.e. "sampleFile") is used to retrieve the uploaded file
   let sampleFile = req.files.sampleFile;

   // Use the mv() method to place the file somewhere on your server
   sampleFile.mv('/somewhere/on/your/server/filename.jpg', function(err) {
   if (err)
      return res.status(500).send(err);

   res.send('File uploaded!');
});

express-fileupload

4
Yago ML

Il me fallait un peu plus de détails que les autres réponses fournies (par exemple, comment puis-je écrire le fichier dans un emplacement que je décide au moment de l'exécution?). J'espère que cela aidera les autres:

obtenir connect-busboy:

npm install connect-busboy --save

Dans votre server.js, ajoutez ces lignes

let busboy = require('connect-busboy')

// ... 

app.use(busboy());

// ... 

app.post('/upload', function(req, res) {
    req.pipe(req.busboy);
    req.busboy.on('file', function(fieldname, file, filename) {
        var fstream = fs.createWriteStream('./images/' + filename); 
        file.pipe(fstream);
        fstream.on('close', function () {
            res.send('upload succeeded!');
        });
    });
});

Cela semblerait omettre le traitement des erreurs, mais le modifiera si je le trouve.

3
Edward Newell

Voici un moyen plus simple qui a fonctionné pour moi:

const express = require('express');
var app = express();
var fs = require('fs');

app.post('/upload', async function(req, res) {

  var file = JSON.parse(JSON.stringify(req.files))

  var file_name = file.file.name

  //if you want just the buffer format you can use it
  var buffer = new Buffer.from(file.file.data.data)

  //uncomment await if you want to do stuff after the file is created

  /*await*/
  fs.writeFile(file_name, buffer, async(err) => {

    console.log("Successfully Written to File.");


    // do what you want with the file it is in (__dirname + "/" + file_name)

    console.log("end  :  " + new Date())

    console.log(result_stt + "")

    fs.unlink(__dirname + "/" + file_name, () => {})
    res.send(result_stt)
  });


});
0
hamzan

Multer est un middleware node.js pour la gestion de multipart/form-data, principalement utilisé pour le téléchargement de fichiers. Il est écrit sur busboy pour une efficacité maximale.

npm install --save multer


in app.js

    var multer  =   require('multer');
    var storage = multer.diskStorage({
      destination: function (req, file, callback) {
        callback(null, './public/uploads');
      },
      filename: function (req, file, callback) {
        console.log(file);
        callback(null, Date.now()+'-'+file.originalname)
      }
    });

    var upload = multer({storage: storage}).single('photo');

    router.route("/storedata").post(function(req, res, next){

        upload(req, res, function(err) {
          if(err) {
            console.log('Error Occured');
            return;
          }
          var userDetail = new mongoOp.User({
            'name':req.body.name,
            'email':req.body.email,
            'mobile':req.body.mobile,
            'address':req.body.address
          });

          console.log(req.file);

          res.end('Your File Uploaded');
          console.log('Photo Uploaded');

          userDetail.save(function(err,result){
          if (err) {
            return console.log(err)
          }
          console.log('saved to database') 
        })
      })

      res.redirect('/')

    });
0
vipinlalrv