Carga de archivos con Express 4.0: req.files undefined

239

Estoy tratando de obtener un mecanismo simple de carga de archivos que funcione con Express 4.0, pero sigo undefinedbuscando req.filesen el app.postcuerpo. Aquí está el código relevante:

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

.. y el código Pug que lo acompaña:

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

Solución
Gracias a la respuesta de mscdex a continuación, he cambiado a usar en busboylugar 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
fuente
1
¿Cómo funciona esto con varios archivos?
chovy
@chovy debería funcionar bien con varios archivos
mscdex
2
Creo que es posible hacer app.post ('/ fileupload', busboy (), function (req, res) {
Shimon Doodkin
Buena solución Solo quería señalar que debe crear un ./files/directorio en el directorio de inicio de su aplicación; de lo contrario, recibirá un error después de cargarlo.
salsa
¿Cómo se manejan los archivos temporales? ¿Busboy los elimina automáticamente? Simplemente no veo que se eliminen archivos temporales antes de guardarlos en el disco.
ed-ta

Respuestas:

210

El body-parsermódulo solo maneja envíos de formularios JSON y urlencoded, no multiparte (que sería el caso si está cargando archivos).

Para multiparte, necesitaría usar algo como connect-busboyo multero connect-multiparty(multiparte / formidable es lo que se usó originalmente en el middleware express bodyParser). También FWIW, estoy trabajando en una capa de nivel aún más alto en la parte superior de busboy llamado reformed. Viene con un middleware Express y también se puede usar por separado.

mscdex
fuente
44
Gracias, eso funcionó. Aunque tuve que usar en connect-busboylugar de solo busboy. Actualicé mi publicación original con la solución.
safwanc
44
¡Gracias amigo! ¡Encuentro la connect-multipartymejor opción de estas!
neciu
¿ reformedTodavía está en desarrollo? Su último commit en github es de 2014 ... Por cierto, en su opinión, ¿cuál es el mejor módulo para manejar datos de formularios multiparte? Por "mejor" me refiero al mejor compatible y al que funciona mejor (menos errores), con más funciones y con un futuro más largo ... Elegí multerporque parecía el mejor compatible, pero todavía creo que debería ser más compatible.
nbro
[EDITAR: está bien, acabo de ver la respuesta a continuación.] ¿Hizo multiparte en express 3.0 y luego se rompió en 4.0? pregunto porque este tutorial usa 3.4.8 y puede cargar archivos sin la necesidad de ningún middleware adicional blog.robertonodi.me/simple-image-upload-with-express
thetrystero
@thetrystero El repositorio de github para ese ejemplo en particular al que se vinculó tiene las dependencias registradas en el repositorio. Si explora esas dependencias, verá que se incluye Express 3.x, así como Connect 2.x (que todavía tenía un módulo multiparte incluido). Es por eso que el manejo multiparte funcionaba "fuera de la caja".
mscdex
31

Esto es lo que encontré buscando en Google:

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

Que es un mecanismo bastante simple para cargas

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
fuente
demasiado lento para archivos grandes
Eduardo
3
¿No lo usaste fileupload?
BrandonFlynn-NB
55
Para que la respuesta anterior funcione, debe agregar estas dos líneas en su principalapp.js const fileUpload = require('express-fileupload') app.use(fileUpload())
abhishake el
11

Parece body-parser que admitía cargar archivos en Express 3, pero se eliminó el soporte para Express 4 cuando ya no incluía Connect como una dependencia

Después de revisar algunos de los módulos en la respuesta de mscdex, descubrí que express-busboyera una alternativa mucho mejor y lo más parecido a un reemplazo directo . Las únicas diferencias que noté estaban en las propiedades del archivo cargado.

console.log(req.files)usando body-parser (Express 3) genera un objeto que se ve así:

{ 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 } }

en comparación con el console.log(req.files)uso 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
fuente
8

1) Asegúrese de que su archivo se envíe realmente desde el lado del cliente. Por ejemplo, puede verificarlo en Chrome Console: captura de pantalla

2) Aquí está el ejemplo básico del 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
fuente
7

multer es un middleware que maneja "datos multiparte / formulario" y mágicamente hace que los archivos cargados y los datos del formulario estén disponibles para nosotros como request.files y request.body.

instalación de multer: - npm install multer --save

en archivo .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>

en archivo .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
});

¡Espero que esto ayude!

Parth Raval
fuente
2

Por favor use el siguiente código

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

PROBLEMA RESUELTO !!!!!!!

Resulta que la storagefunción NO se ejecutó ni una sola vez. porque tuve que incluir app.use(upload)comoupload = 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
fuente
-1

express-fileupload parece el único middleware que aún funciona en estos días.

Con el mismo ejemplo, multery connect-multipartyda un valor indefinido de req.file o req.files , pero express-fileuploadfunciona.

Y hay muchas preguntas y cuestiones planteadas sobre el valor vacío de req.file / req.files .

trd
fuente