Hochladen von Knoten- / Express-Dateien

93

Ich verwende Node v0.10.26 und Express v4.2.0 und bin ziemlich neu in Node. Ich habe in den letzten drei Stunden meinen Kopf gegen meinen Schreibtisch geschlagen und versucht, ein Formular zum Hochladen von Dateien mit Node zum Laufen zu bringen. An dieser Stelle versuche ich nur, req.files dazu zu bringen, nicht undefiniert zurückzugeben. Meine Ansicht sieht so aus

<!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>

Hier sind meine Routen

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;

Und hier ist meine 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;

Ich habe irgendwo gesehen, dass einschließlich methodOverride()und bodyParser({keepExtensions:true,uploadDir:path})sollte helfen, aber ich kann meinen Server nicht einmal starten, wenn ich diese Zeilen hinzufüge.

okawei
quelle
Ich habe Express 3 anstelle von 4 verwendet, damit die API geändert werden kann, aber ich denke, Sie müssen googeln / bing formidableund express. AFAIK müssen Sie aktivieren, formiabledas die Verantwortung für den Umgang mit mehrteiligen Formulardaten übernimmt, die Dateien auf der lokalen Festplatte speichert (was das uploadDirMittel ist), dann können Sie sie verwenden req.files, um sie zu lesen und Ihre Geschäftslogik zu verarbeiten.
Shaun Xu
Versuchen Sie, "var bodyParser = require ('body-parser');" und anstatt diese bodyParser-Variable zu verwenden, verwenden Sie Folgendes: app.use (express.bodyParser ()); app.use (express.methodOverride ()); Ich habe nicht die Zeit, diese
Atmosphäre
Es ist spät, kann aber für jemanden in Zukunft hilfreich sein. Hier ist ein vollständiges Tutorial zum Hochladen von Knoten-JS-Dateien mit mongodb programmerblog.net/nodejs-file-upload-tutorial
Jason W
Wofür ist diese Zeile? app.use(express.static(path.join(__dirname, 'public')));
Geoidesic

Antworten:

94

ExpressJS-Problem:

Der größte Teil der Middleware wird aus Express 4 entfernt. Check out: http://www.github.com/senchalabs/connect#middleware Für mehrteilige Middleware wie Busboy, Busboy-Connect, Formidable, Flow, Parted wird benötigt.

In diesem Beispiel wird die Connect-Busboy- Middleware verwendet. Erstelle / img und / öffentliche Ordner.
Verwenden Sie die Ordnerstruktur:

\ server.js

\ img \ "wo Sachen hochgeladen werden"

\ 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>

Das Folgende funktioniert mit beeindruckendem 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);
});
Mick Cullen
quelle
34
Wir haben also ein Framework, das wichtige APIs ändert und grundlegende Dinge schrecklich kompliziert macht. Und das ist das beliebteste NodeJS-Modul?
Wortwart
18
Es ist eine Hauptversion. Aktuelle Änderungen sind in Hauptversionen gemäß der semver.org-Spezifikation zulässig.
Stuart P. Bentley
6
Sicher, semver.org erlaubt es, API-Änderungen in wichtigen Versionsnummern zu brechen, aber das ist ein schrecklicher Punkt, wenn Sie versuchen, Ihre Benutzer zu verärgern.
joonas.fi
1
Ich habe seit Tagen Probleme damit, einen Datei-Upload für Express zu erhalten. Danke dir!!!
aProperFox
1
Äh, was genau ist "bodyParser" und woher kommt es? @ Mick
Robin
27

Eine andere Möglichkeit ist die Verwendung von Multer , bei dem Busboy unter der Haube verwendet wird, der jedoch einfacher einzurichten ist.

var multer = require('multer');

Verwenden Sie multer und legen Sie das Ziel für den Upload fest:

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

Erstellen Sie ein Formular in Ihrer Ansicht, enctype='multipart/form-datadamit Multer funktioniert:

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

Dann können Sie in Ihrem POST auf die Daten über die Datei zugreifen:

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

Ein vollständiges Tutorial dazu finden Sie hier .

Carasel
quelle
4
Ich bewege mich von Multer weg, nachdem ich mit unknown fieldFehlern frustriert bin . Alles in meinem Code ist korrekt. Es funktioniert die meiste Zeit und zeigt dann auf mysteriöse Weise diese Ausnahme, wobei alles gleich bleibt (Umgebung, Datei, Code, Dateiname)
kishu27
neuen TypeError auslösen ('app.use () erfordert Middleware-Funktionen');
Kris
Möglicherweise möchten Sie dies so einrichten, wenn Sie Probleme mit der Übergabe der Multer-Funktion an app.use `` `var upload = multer ({dest: 'uploads /'}) haben. var app = express () app.post ('/ profile', upload.single ('Feldname'), Funktion (req, res, next) {console.log (req.file);}) `` `
Anibe Agamah
22

Hier ist eine vereinfachte Version ( das Wesentliche ) von Mick Cullens Antwort - teilweise um zu beweisen, dass es nicht sehr komplex sein muss, dies umzusetzen; Zum Teil, um eine Kurzreferenz für alle zu geben, die nicht daran interessiert sind, Seiten und Codeseiten zu lesen.


Sie müssen Ihre App dazu bringen, Connect-Busboy zu verwenden :

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

Dies wird nichts tun, bis Sie es auslösen. Gehen Sie in dem Aufruf, der das Hochladen übernimmt, wie folgt vor:

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

Lassen Sie uns das zusammenfassen:

  • Sie überprüfen, ob req.busboyeingestellt ist (die Middleware wurde korrekt geladen)
  • Sie haben einen "file"Listener eingerichtetreq.busboy
  • Sie leiten den Inhalt von reqanreq.busboy

Im Datei-Listener gibt es einige interessante Dinge, aber was wirklich wichtig ist, fileStreamist Folgendes : Dies ist eine lesbare Datei, die dann wie gewohnt in eine Datei geschrieben werden kann.

Fallstricke: Sie müssen mit Readable umgehen, da Express sonst niemals auf die Anfrage reagiert (siehe Busboy-API ( Dateibereich )).

Niels Abildgaard
quelle
17

Ich finde das einfach und effizient:

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

// default options
app.use(fileUpload());

app.post('/upload', function(req, res) {
  if (!req.files || Object.keys(req.files).length === 0) {
    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-Datei hochladen

Yago ML
quelle
Wer nach einer neueren Lösung mit einem aktuellen NPM-Paket sucht, sollte hier nachsehen. Express-Fileupload macht dies wirklich einfach.
Jaredbaszler
4

Ich musste etwas detaillierter durchgehen als die anderen Antworten (z. B. wie schreibe ich die Datei an einen Ort, den ich zur Laufzeit festgelegt habe?). Hoffentlich hilft dies anderen:  

Holen Sie sich Connect-Busboy:

npm install connect-busboy --save

Fügen Sie in Ihrer server.js diese Zeilen hinzu

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

Dies scheint jedoch die Fehlerbehandlung zu unterlassen ... wird bearbeitet, wenn ich es finde.

Edward Newell
quelle
1

Multer ist eine node.js-Middleware für den Umgang mit mehrteiligen / Formulardaten, die hauptsächlich zum Hochladen von Dateien verwendet wird. Es ist für maximale Effizienz auf den Busboy geschrieben.

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('/')

    });
vipinlalrv
quelle
Multer ist eine node.js-Middleware für den Umgang mit mehrteiligen / Formulardaten, die hauptsächlich zum Hochladen von Dateien verwendet wird. Es ist für maximale Effizienz auf den Busboy geschrieben.
Vipinlalrv
Zum besseren Verständnis habe ich Ihre Antwort mit Ihrem Kommentarbereich bearbeitet, ich hoffe, es macht Ihnen nichts aus: P
Pardeep Jain
1

Hier ist ein einfacher Weg, der für mich funktioniert hat:

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


});
hamzan
quelle
Oh wow, das ist eine interessante Implementierung. Funktioniert es gut für verschiedene Dateiformate?
Merunas Grincalaitis
0

Persönlich hat multer nach Wochen, in denen ich versucht habe, diese Datei hochzuladen, nicht für mich funktioniert. Dann wechsle ich zu formidable und nach ein paar Tagen habe ich es perfekt ohne Fehler zum Laufen gebracht, mehrere Dateien, express und react.js, obwohl react optional ist. Hier ist die Anleitung: https://www.youtube.com/watch?v=jtCfvuMRsxE&t=122s

Merunas Grincalaitis
quelle
0

Wenn Sie Node.js Express verwenden und Typescript hier ein funktionierendes Beispiel ist, funktioniert dies auch mit Javascript. Ändern Sie einfach let in var und import in include etc ...

Importieren Sie zuerst Folgendes: Stellen Sie sicher, dass Sie formidable installieren, indem Sie den folgenden Befehl ausführen:

npm install formidable

als importieren Sie die folgenden:

  import * as formidable from 'formidable';
  import * as fs from 'fs';

dann deine Funktion wie unten:

    uploadFile(req, res) {
    let form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        let oldpath = files.file.path;
        let newpath = 'C:/test/' + files.file.name;
        fs.rename(oldpath, newpath, function (err) {
            if (err) throw err;
            res.write('File uploaded and moved!');
            res.end();
        });
    });
}
MJ X.
quelle