Upload de arquivo com o Express 4.0: req.files indefinido

239

Eu estou tentando obter um simples upload de arquivos mecanismo de trabalho com Express 4.0, mas eu continuo recebendo undefinedpara req.filesno app.postcorpo. Aqui está o 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'); 
}); 

.. e o código Pug que o acompanha:

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

Solução
Graças à resposta do mscdex abaixo, mudei para usar em busboyvez 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
fonte
1
como isso funciona com vários arquivos?
chovy
@chovy ele deve funcionar muito bem com vários arquivos
mscdex
2
acho que é possível fazer app.post ('/ fileupload', busboy (), função (req, res)) {
Shimon Doodkin
Boa solução Gostaria apenas de observar que você precisa criar um ./files/diretório no diretório inicial do aplicativo, caso contrário, você receberá um erro após o upload.
sauce
Como os arquivos temporários são manipulados? O busboy os exclui automaticamente? Eu simplesmente não vejo nenhum arquivo temporário sendo excluído antes de salvar no disco.
ed-ta

Respostas:

210

O body-parsermódulo lida apenas com envios de formulários JSON e codificados por url, não com várias partes (o que seria o caso se você estiver carregando arquivos).

Para multipartes, você precisa usar algo como connect-busboyor multeror connect-multiparty(multiparty / formidable é o que foi originalmente usado no middleware express bodyParser). Também FWIW, estou trabalhando em uma camada de nível ainda mais alto em cima do busboy chamado reformed. Ele vem com um middleware Express e também pode ser usado separadamente.

mscdex
fonte
4
Obrigado, isso funcionou. Embora eu tivesse que usar em connect-busboyvez de apenas busboy. Atualizei minha postagem original com a solução.
safwanc
4
Obrigado companheiro! Acho a connect-multipartymelhor opção destes!
Nciu
reformedAinda está em desenvolvimento? Seu último commit no github é de 2014 ... Aliás, na sua opinião, qual é o melhor módulo para lidar com dados de formulários de várias partes? Por "melhor", quero dizer o melhor suportado e o que funciona melhor (menos bugs), com mais recursos e com um futuro mais longo ... escolhi multerporque parecia o melhor suportado, mas ainda acho que deveria ser mais suportado.
Nbro
[EDIT: tudo bem, só vi a resposta abaixo.] Fez multipart no express 3.0 e depois foi quebrado no 4.0? Eu pergunto porque este tutorial usa 3.4.8 e pode fazer upload de arquivos sem a necessidade de qualquer middleware adicional blog.robertonodi.me/simple-image-upload-with-express
thetrystero
@thetrystero O repositório do github para esse exemplo específico ao qual você vinculou realmente tem as dependências verificadas no repositório. Se você pesquisar nessas dependências, verá que o Express 3.x está incluído, bem como o Connect 2.x (que ainda tinha um módulo de várias partes incluído). É por isso que o manuseio de várias partes estava funcionando "fora da caixa".
mscdex
31

Aqui está o que eu encontrei pesquisando:

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

O que é um mecanismo bastante simples para uploads

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
fonte
demasiado lento para arquivos grandes
Eduardo
3
Você não usou fileupload?
BrandonFlynn-NB
5
Para a resposta acima para o trabalho, você precisa adicionar essas duas linhas em sua principalapp.js const fileUpload = require('express-fileupload') app.use(fileUpload())
abhishake
11

Parece body-parser que suportou o upload de arquivos no Express 3, mas o suporte foi descartado para o Express 4 quando não incluiu mais o Connect como uma dependência

Depois de examinar alguns dos módulos na resposta do mscdex, descobri que express-busboyera uma alternativa muito melhor e a coisa mais próxima de uma substituição imediata . As únicas diferenças que notei foram nas propriedades do arquivo carregado.

console.log(req.files)usando body-parser (Express 3) produz um objeto parecido com isto:

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

comparado ao console.log(req.files)uso do 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
fonte
8

1) Verifique se o seu arquivo é realmente enviado do lado do cliente. Por exemplo, você pode verificá-lo no Chrome Console: captura de tela

2) Aqui está o exemplo básico do back-end do 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
fonte
7

O multer é um middleware que lida com “multipart / form-data” e magicamente e disponibiliza os arquivos e dados do formulário enviados a nós, a pedido, como request.files e request.body.

instalação multer: - npm install multer --save

no arquivo .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>

no arquivo .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 isto ajude!

Parth Raval
fonte
2

Por favor, use o código abaixo

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

PROBLEMA RESOLVIDO !!!!!!!

Acontece que a storagefunção NÃO executou nem uma vez. porque eu tive 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
fonte
-1

express-fileupload parece o único middleware que ainda funciona atualmente.

Com o mesmo exemplo, multere connect-multipartyfornece um valor indefinido de req.file ou req.files , mas express-fileuploadfunciona.

E há muitas perguntas e questões levantadas sobre o valor vazio de req.file / req.files .

trd
fonte