Champ inattendu Node Multer


134

Je travaille sur le téléchargement d'un fichier sur mon application à l'aide du module multer npm.

La fonction de multer que j'ai définie est d'autoriser le téléchargement d'un seul fichier dans le système de fichiers. Tout fonctionne pendant l'exécution; le problème est qu'après avoir téléchargé le fichier, j'obtiens une erreur ci-dessous. Tout conseil apprécié sur où chercher.

Erreur:

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

Réponses:


139

Nous devons nous assurer que le type = file avec l'attribut name doit être le même que le nom du paramètre passé 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
Pourriez-vous expliquer pourquoi cela fonctionne et ce qui est différent? —_____—
IIllIIll

8
Fonctionne parfaitement comme charm.Nous devons nous assurer que le type = file avec l'attribut name doit être le même que le nom du paramètre passé dans upload.single ('attr')
Ramki

1
Mon cas, ça ne marche pas. Je suis confronté au même problème. Mais dans mon code machine Windows fonctionne. J'ai des problèmes avec mon MAC.? Quelqu'un peut-il m'aider avec ça?
HaRdik Kaji

6
L'attribut name du type = "file" en html doit correspondre au upload.single ('name') dans le code serveur.
Prasanth Jaya

Comment définir la demande du client pour un téléchargement de plusieurs fichiers? Le champ «fichiers» est vide.
吳 強 福

219

La fonction que <NAME>vous utilisez dans multer upload.single(<NAME>)doit être la même que celle que vous utilisez dans <input type="file" name="<NAME>" ...>.

Alors tu dois changer

var type = upload.single('file')

à

var type = upload.single('recfile')

dans vous app.js

J'espère que cela t'aides.


2
Cela aiderait s'ils le mettaient dans le readme au lieu de le remplir avec «avatar».
hugos

1
Mais il faut quand même éviter l'exception en cas de mauvaise utilisation .. comment intercepter cette exception?
syberkitten

Juste pour référence, si vous utilisez curl et que la commande ressemble à ceci: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Ensuite, la valeur de upload.single est "upload"
chrismarx

19

Une suite à la réponse de Vincent.

Pas de réponse directe à la question puisque la question utilise un formulaire.

Pour moi, ce n'est pas le nom de la balise d'entrée qui a été utilisée, mais le nom lors de l'ajout du fichier au formData.

fichier frontal

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

fichier de service Web:

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

Cela m'a sauvé la journée. Je vous remercie. Si vous utilisez FormData.append (), l'attribut de nom de la balise <input> sera écrasé et empêchera les autres solutions de fonctionner.
Schmidko

1
Cette réponse est si importante et incroyablement utile. Il formDataest essentiel de s'assurer que le nom de la clé est le même que l' uploadargument clé. Ça marche pour moi maintenant.
Moderme

4

puisque 2 images sont téléchargées! un avec extension de fichier et un autre fichier sans extension. pour supprimer tmp_path (fichier sans extension)

après
src.pipe(dest);

ajouter ci-dessous le code

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


4

Ceci pour l'API que vous pourriez utiliser

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

Cela fonctionne également très bien utilisé sur Postman mais le fichier n'est pas livré avec l'extension .jpg. Comme commenté ci-dessous

Il s'agit de la fonctionnalité par défaut de multer si le fichier télécharge sans extension, cependant, vous fournit l'objet fichier, à l'aide duquel vous pouvez mettre à jour l'extension du fichier.

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

Malheureusement, le message d'erreur ne fournit pas d'informations claires sur le vrai problème. Pour cela, un certain débogage est nécessaire.

À partir de la trace de la pile, voici l'origine de l'erreur dans le multerpackage:

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

Et la traduction étrange (peut-être erronée) appliquée ici est la source du message lui-même ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLeftest un objet qui contient le nom du champ attendu par votre serveur et qui file.fieldnamecontient le nom du champ fourni par le client. L'erreur est renvoyée en cas d'incohérence entre le nom de champ fourni par le client et le nom de champ attendu par le serveur.

La solution est de changer le nom sur le client ou le serveur afin que les deux soient d' accord.

Par exemple, lors de l'utilisation fetchsur le client ...

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

Et le serveur aurait une route telle que la suivante ...

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

Notez que c'est myfilele nom commun (dans cet exemple).


Merci beaucoup. Votre commentaire m'a donné un indice sur mon erreur. Dans mon cas, j'avais 2 formes dans différentes vues et différents fichiers de routeur. Le premier routeur a utilisé le champ de nom avec la vue 1 et son nom de fichier était "imgLoading". La deuxième vue avait un autre nom que le fichier d'entrée. Pour une raison quelconque, multer ne vous permet pas de définir des noms différents dans différentes vues, j'ai donc utilisé le même nom pour l'entrée de fichier dans les deux vues.
Luis Armando

1

Je résous ces problèmes en recherchant le nom que j'ai transmis à ma demande

J'envoyais sur le corps:

{thumbbail: <myimg>}

et je m'attendais à:

upload.single('thumbnail')

donc, je fixe le nom qu'un envoi sur demande


1

Nom de fichier différent qui a été publié comme " recfile " à <input type="file" name='recfile' placeholder="Select file"/>et reçu comme " fichier " à upload.single('file')

Solution : assurez-vous que les fichiers envoyés et reçus sont similairesupload.single('recfile')


0

Dans mon scénario, cela se produisait car j'ai renommé un paramètre dans swagger.yamlmais je n'ai pas rechargé la page de documentation.

Par conséquent, j'essayais l'API avec un paramètre d'entrée inattendu.
Longue histoire courte, F5est mon ami.


0

vous ne donnez probablement pas le même nom que celui que vous avez mentionné dans le upload.single('file').


0

Dans mon cas, j'avais 2 formes dans différentes vues et différents fichiers de routeur. Le premier routeur a utilisé le champ de nom avec la vue 1 et son nom de fichier était "inputGroupFile02". La deuxième vue avait un autre nom pour l'entrée de fichier. Pour une raison quelconque, Multer ne vous permet pas de définir des noms différents dans différentes vues, j'ai donc décidé d'utiliser le même nom pour l'entrée de fichier dans les deux vues.

entrez la description de l'image ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.