Campo inesperado do Nó Multer


134

Estou trabalhando no upload de um arquivo para o meu aplicativo usando o módulo multer npm.

A função multer que defini é permitir que um único arquivo seja carregado no sistema de arquivos. Tudo funciona durante o tempo de execução; o problema ocorre após o upload do arquivo. Recebo um erro abaixo. Qualquer conselho apreciado sobre onde procurar.

Erro:

Unexpected field

Error: Unexpected field
    at makeError (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\lib\make-error.js:12:13)
    at wrappedFileFilter (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\index.js:39:19)
    at Busboy.<anonymous> (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\lib\make-middleware.js:97:7)
    at Busboy.emit (events.js:118:17)
    at Busboy.emit (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\node_modules\busboy\lib\main.js:31:35)
    at PartStream.<anonymous> (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\node_modules\busboy\lib\types\multipart.js:205:13)
    at PartStream.emit (events.js:107:17)
    at HeaderParser.<anonymous> (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\node_modules\busboy\node_modules\dicer\lib\Dicer.js:51:16)
    at HeaderParser.emit (events.js:107:17)
    at HeaderParser._finish (c:\Users\Dev\WebstormProjects\Crunch\node_modules\multer\node_modules\busboy\node_modules\dicer\lib\HeaderParser.js:70:8) 

app.js

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

//. . . 

var upload = multer({ dest: 'upload/'});
var type = upload.single('file');

app.post('/upload', type, function (req,res) {
  var tmp_path = req.files.recfile.path;
  var target_path = 'uploads/' + req.files.recfile.name;
fs.readFile(tmp_path, function(err, data)
{
  fs.writeFile(target_path, data, function (err)
  {
    res.render('complete');
  })
});

Index.hbs

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name='recfile' placeholder="Select file"/>
    <br/>
    <button>Upload</button>
</form>

#Package.json
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "easy-zip": "0.0.4",
    "express": "~4.13.1",
    "hbs": "~3.1.0",
    "less-middleware": "1.0.x",
    "morgan": "~1.6.1",
    "multer": "~1.0.0",
    "serve-favicon": "~2.3.0"
  }
}

Respostas:


139

Temos que garantir que o arquivo type = file com o atributo name seja igual ao nome do parâmetro passado em upload.single('attr')

var multer  = require('multer');
var upload = multer({ dest: 'upload/'});
var fs = require('fs');

/** Permissible loading a single file, 
    the value of the attribute "name" in the form of "recfile". **/
var type = upload.single('recfile');

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

  /** When using the "single"
      data come in "req.file" regardless of the attribute "name". **/
  var tmp_path = req.file.path;

  /** The original name of the uploaded file
      stored in the variable "originalname". **/
  var target_path = 'uploads/' + req.file.originalname;

  /** A better way to copy the uploaded file. **/
  var src = fs.createReadStream(tmp_path);
  var dest = fs.createWriteStream(target_path);
  src.pipe(dest);
  src.on('end', function() { res.render('complete'); });
  src.on('error', function(err) { res.render('error'); });

});

89
Você se importaria de explicar por que isso funciona e o que é diferente? -_____-
IIllIIll

8
Funciona perfeitamente como charm.We tem que ter certeza do tipo = arquivo com atributo de nome deve ser igual ao nome do parâmetro passado upload.single ( 'attr')
Ramki

1
O meu caso não está funcionando. Estou enfrentando o mesmo problema. Mas no meu código de máquina do Windows está funcionando. Estou tendo problemas com o meu MAC.? Alguém pode me ajudar nisso?
HaRdik Kaji

6
O atributo name do type = "file" em html deve corresponder ao upload.single ('name') no código do servidor.
Prasanth Jaya

Como definir a solicitação do cliente para um upload de vários arquivos? O campo 'arquivos' está vazio.
吳強福

219

A função que <NAME>você usa na multer upload.single(<NAME>)deve ser a mesma que você usa <input type="file" name="<NAME>" ...>.

Então você precisa mudar

var type = upload.single('file')

para

var type = upload.single('recfile')

em você app.js

Espero que isto ajude.


2
Ajudaria se eles colocassem isso no leia-me em vez de preenchê-lo com 'avatar'.
Hugos

1
Mas ainda precisamos evitar a exceção em caso de uso indevido. Como capturar essa exceção?
29817 syberkitten

Apenas para referência, se você estiver usando curl, e o comando estiver assim: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Em seguida, o valor para upload.single é "upload"
chrismarx

19

Um seguimento da resposta de vincent.

Não é uma resposta direta à pergunta, pois ela está usando um formulário.

Para mim, não era o nome da tag de entrada usada, mas o nome ao anexar o arquivo ao formData.

arquivo front-end

   var formData = new FormData();
   formData.append('<NAME>',this.new_attachments)

arquivo de serviço da web:

   app.post('/upload', upload.single('<NAME>'),...

Isso salvou meu dia. Obrigado. Se você usar FormData.append (), o nome atribuído da marca <input> será substituído e fará com que as outras soluções não funcionem.
Schmidko 25/05

1
Esta resposta é tão importante e incrivelmente útil. É crucial garantir que o formDatanome da chave seja o mesmo que o uploadargumento da chave. Trabalha para mim agora.
Modermo

4

desde que 2 imagens estão sendo carregadas! um com extensão de arquivo e outro arquivo sem extensão. excluir tmp_path (arquivo sem extensão)

depois de
src.pipe(dest);

adicione código abaixo

fs.unlink(tmp_path); //deleting the tmp_path


4

Isso para a API você pode usar

 const express        = require('express');
 const bodyParser     = require('body-parser');
 const app = express();
 var multer = require('multer');
 const port = 8000;
 app.use(bodyParser.json());
 app.use(bodyParser.urlencoded({ extended: true }));

 app.listen(port, ()=>{
 console.log('We are live on' + port);
 });

 var upload = multer({dest:'./upload/'});

 app.post('/post', upload.single('file'), function(req, res) {
  console.log(req.file);
 res.send("file saved on server");
 });

Isso também funciona bem no Postman, mas o arquivo não vem com a extensão .jpg. Como comentado abaixo

Esse é o recurso padrão do multer se o upload de arquivo sem extensão for fornecido, no entanto, você fornecerá o objeto de arquivo, usando o qual você poderá atualizar a extensão do arquivo.

var filename = req.file.filename; 
var mimetype = req.file.mimetype; 
mimetype = mimetype.split("/"); 
var filetype = mimetype[1]; 
var old_file = configUploading.settings.rootPathTmp+filename; 
var new_file = configUploading.settings.rootPathTmp+filename+'.'+filetype; 
rname(old_file,new_file);

1

Infelizmente, a mensagem de erro não fornece informações claras sobre qual é o verdadeiro problema. Para isso, é necessária alguma depuração.

No rastreamento da pilha, aqui está a origem do erro no multerpacote:

function wrappedFileFilter (req, file, cb) {
  if ((filesLeft[file.fieldname] || 0) <= 0) {
    return cb(makeError('LIMIT_UNEXPECTED_FILE', file.fieldname))
  }

  filesLeft[file.fieldname] -= 1
  fileFilter(req, file, cb)
}

E a tradução estranha (possivelmente equivocada) aplicada aqui é a fonte da própria mensagem ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLefté um objeto que contém o nome do campo que seu servidor está esperando e file.fieldnamecontém o nome do campo fornecido pelo cliente. O erro é gerado quando há uma incompatibilidade entre o nome do campo fornecido pelo cliente e o nome do campo esperado pelo servidor.

A solução é alterar o nome no cliente ou no servidor para que os dois concordem.

Por exemplo, ao usar fetchno cliente ...

var theinput = document.getElementById('myfileinput')
var data = new FormData()
data.append('myfile',theinput.files[0])
fetch( "/upload", { method:"POST", body:data } )

E o servidor teria uma rota como a seguinte ...

app.post('/upload', multer(multerConfig).single('myfile'),function(req, res){
  res.sendStatus(200)
}

Observe que esse é myfileo nome comum (neste exemplo).


Muito obrigado. Seu comentário me deu uma dica sobre o meu erro. No meu caso, eu tinha 2 formulários em diferentes visualizações e diferentes arquivos de roteador. O primeiro roteador usou o campo de nome com a exibição um e seu nome de arquivo era "imgLoading". A segunda visualização tinha outro nome, a entrada do arquivo. Por algum motivo, o multer não permite que você defina o nome diferente em diferentes visualizações, por isso eu usei o mesmo nome para a entrada do arquivo em ambas as visualizações.
Luis Armando

1

Resolvo esses problemas procurando o nome que passei na minha solicitação

Eu estava enviando no corpo:

{thumbbail: <myimg>}

e eu esperava:

upload.single('thumbnail')

então, eu corrijo o nome que um envio a pedido


1

Nome de arquivo diferente que foi postado como " refil " <input type="file" name='recfile' placeholder="Select file"/>e recebido como " arquivo " em upload.single('file')

Solução : verifique se os arquivos enviados e recebidos são semelhantesupload.single('recfile')


0

No meu cenário, isso estava acontecendo porque renomeei um parâmetro, swagger.yamlmas não recarreguei a página de documentos.

Portanto, eu estava tentando a API com um parâmetro de entrada inesperado.
Para encurtar a história, F5é meu amigo.


0

provavelmente você não está dando o mesmo nome que você mencionou no upload.single('file').


0

No meu caso, eu tinha 2 formulários em diferentes visualizações e diferentes arquivos de roteador. O primeiro roteador usou o campo de nome com a exibição um e seu nome de arquivo era "inputGroupFile02". A segunda visualização tinha outro nome para a entrada do arquivo. Por alguma razão, o Multer não permite que você defina nomes diferentes em modos de exibição diferentes, então decidi usar o mesmo nome para a entrada do arquivo nos dois modos de exibição.

insira a descrição da imagem aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.