Nodo Multer campo inesperado


134

Estoy trabajando en cargar un archivo a mi aplicación usando el módulo multer npm.

La función multer que he definido es permitir que se cargue un solo archivo en el sistema de archivos. Todo funciona durante el tiempo de ejecución; El problema es que después de cargar el archivo aparece un error a continuación. Cualquier consejo apreciado sobre dónde buscar.

Error:

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

Respuestas:


139

Tenemos que asegurarnos de que el archivo type = con el atributo de nombre debe ser el mismo que el nombre del parámetro pasado 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
¿Te importaría explicar por qué esto funciona y qué es diferente? —_____—
IIllIIll

8
Funciona perfectamente como encanto. Tenemos que asegurarnos de que el tipo = archivo con el atributo de nombre debe ser el mismo que el nombre del parámetro pasado en upload.single ('attr')
Ramki

1
El caso mío no está funcionando. Estoy enfrentando el mismo problema. Pero en mi Windows el código de la máquina está funcionando. Tengo problemas con mi MAC. ¿Alguien puede ayudarme?
HaRdik Kaji

66
El atributo de nombre del tipo = "archivo" en html debe coincidir con upload.single ('nombre') en el código del servidor.
Prasanth Jaya

¿Cómo configurar la solicitud del cliente para una carga de múltiples archivos? El campo 'archivos' está vacío.
吳 強 福

219

La función <NAME>que use en multer upload.single(<NAME>)debe ser la misma que la que usa <input type="file" name="<NAME>" ...>.

Entonces necesitas cambiar

var type = upload.single('file')

a

var type = upload.single('recfile')

en tu app.js

Espero que esto ayude.


2
Sería útil si pusieran esto en el archivo Léame en lugar de llenarlo con 'avatar'.
hugos

1
Pero aún necesitamos evitar la excepción en caso de mal uso ... ¿Cómo atrapar esta excepción?
syberkitten

Solo como referencia, si está usando curl, y el comando se ve así: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Entonces el valor de upload.single es "upload"
chrismarx

19

Un seguimiento a la respuesta de Vincent.

No es una respuesta directa a la pregunta ya que la pregunta está usando un formulario.

Para mí, no fue el nombre de la etiqueta de entrada lo que se usó, sino el nombre al agregar el archivo a formData.

archivo frontal

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

archivo de servicio web:

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

Esto me salvó el día. Gracias. Si usa FormData.append (), el nombre del atributo de la etiqueta <input> se sobrescribirá y hará que las otras soluciones no funcionen.
Schmidko

1
Esta respuesta es muy importante e increíblemente útil. Asegurarse de que el formDatanombre clave sea el mismo que el uploadargumento clave es crucial. Funciona para mi ahora.
Modermo

4

¡ya que se están cargando 2 imágenes! uno con extensión de archivo y otro sin extensión. eliminar tmp_path (archivo sin extensión)

después
src.pipe(dest);

agregue el siguiente código

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


4

Esto para la API podría 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");
 });

Esto también funciona bien en Postman pero el archivo no viene con la extensión .jpg ¿Algún consejo? Como se comenta a continuación

Esta es la característica predeterminada de multer si carga un archivo sin extensión, sin embargo, le proporciona el objeto del archivo, mediante el cual puede actualizar la extensión del archivo.

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

Desafortunadamente, el mensaje de error no proporciona información clara sobre cuál es el verdadero problema. Para eso, se requiere alguna depuración.

Desde el seguimiento de la pila, aquí está el origen del error en el multerpaquete:

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

Y la traducción extraña (posiblemente errónea) aplicada aquí es la fuente del mensaje en sí ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLeftes un objeto que contiene el nombre del campo que su servidor espera y file.fieldnamecontiene el nombre del campo proporcionado por el cliente. El error se produce cuando hay una falta de coincidencia entre el nombre de campo proporcionado por el cliente y el nombre de campo esperado por el servidor.

La solución es cambiar el nombre en el cliente o en el servidor para que los dos estén de acuerdo.

Por ejemplo, cuando se usa fetchen el cliente ...

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

Y el servidor tendría una ruta como la siguiente ...

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

Observe que es myfilecuál es el nombre común (en este ejemplo).


Muchas gracias. Su comentario me dio una pista sobre mi error. En mi caso, tenía 2 formas en diferentes vistas y diferentes archivos de enrutador. El primer enrutador usó el campo de nombre con la vista uno y su nombre de archivo era "imgLoading". La segunda vista tenía otro nombre para la entrada del archivo. Por alguna razón, multer no le permite establecer diferentes nombres en diferentes vistas, por lo que decidí usar el mismo nombre para la entrada del archivo en ambas vistas.
Luis Armando

1

Resuelvo estos problemas buscando el nombre que pasé en mi solicitud

Estaba enviando el cuerpo:

{thumbbail: <myimg>}

y esperaba:

upload.single('thumbnail')

entonces, arreglo el nombre que se envía a pedido


1

Nombre de archivo diferente que se publicó como " archivo " en <input type="file" name='recfile' placeholder="Select file"/>y se recibió como " archivo " en upload.single('file')

Solución : asegúrese de que tanto el archivo enviado como el recibido sean similaresupload.single('recfile')


0

En mi caso, esto sucedía porque cambié el nombre de un parámetro swagger.yamlpero no volví a cargar la página de documentos.

Por lo tanto, estaba probando la API con un parámetro de entrada inesperado.
Larga historia corta, F5es mi amigo.


0

probablemente no esté dando el mismo nombre que mencionó en el upload.single('file').


0

En mi caso, tenía 2 formas en diferentes vistas y diferentes archivos de enrutador. El primer enrutador utilizó el campo de nombre con la vista uno y su nombre de archivo era "inputGroupFile02". La segunda vista tenía otro nombre para la entrada de archivos. Por alguna razón, Multer no le permite establecer diferentes nombres en diferentes vistas, por lo que decidí usar el mismo nombre para la entrada del archivo en ambas vistas.

ingrese la descripción de la imagen aquí

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.