Node Multer unerwartetes Feld


134

Ich arbeite daran, eine Datei mit dem multer npm-Modul in meine App hochzuladen.

Die von mir definierte Multer-Funktion besteht darin, das Hochladen einer einzelnen Datei in das Dateisystem zuzulassen. Alles funktioniert zur Laufzeit; Das Problem ist, dass nach dem Hochladen der Datei unten eine Fehlermeldung angezeigt wird. Jeder Rat geschätzt, wo zu suchen.

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

Antworten:


139

Wir müssen sicherstellen, dass die Datei type = file mit dem Attribut name mit dem übergebenen Parameternamen übereinstimmt 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
Würde es Ihnen etwas ausmachen zu erklären, warum dies funktioniert und was anders ist? —_____—
IIllIIll

8
Funktioniert perfekt wie charm.Wir müssen sicherstellen, dass die Datei type = file mit dem Attribut name mit dem Parameternamen übereinstimmt, der in upload.single ('attr') übergeben wurde
Ramki

1
Mein Fall, es funktioniert nicht. Ich stehe vor dem gleichen Problem. Aber in meinem Windows funktioniert der Maschinencode. Ich habe Probleme mit meinem MAC. Kann mir jemand dabei helfen?
HaRdik Kaji

6
Das name-Attribut vom Typ = "file" in HTML sollte mit der upload.single ('name') im Servercode übereinstimmen.
Prasanth Jaya

Wie stelle ich die Client-Anfrage für einen Upload mehrerer Dateien ein? Das Feld 'Dateien' ist leer.
強 福

219

Die Funktion, die <NAME>Sie in multer verwenden, upload.single(<NAME>)muss mit der Funktion übereinstimmen, die Sie verwenden <input type="file" name="<NAME>" ...>.

Sie müssen sich also ändern

var type = upload.single('file')

zu

var type = upload.single('recfile')

in dir app.js.

Hoffe das hilft.


2
Es wäre hilfreich, wenn sie dies in die Readme-Datei aufnehmen würden, anstatt es mit "Avatar" zu füllen.
Hugos

1
Aber wir müssen die Ausnahme im Falle eines Missbrauchs trotzdem vermeiden. Wie kann man diese Ausnahme abfangen?
Syberkitten

Nur als Referenz, wenn Sie curl verwenden und der Befehl folgendermaßen aussieht: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Dann lautet der Wert für upload.single "upload"
chrismarx

19

Eine Fortsetzung der Antwort von Vincent.

Keine direkte Antwort auf die Frage, da die Frage ein Formular verwendet.

Für mich wurde nicht der Name des Eingabe-Tags verwendet, sondern der Name beim Anhängen der Datei an die formData.

Frontend-Datei

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

Webdienstdatei:

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

Das hat mir den Tag gerettet. Danke dir. Wenn Sie FormData.append () verwenden, wird das Namensattribut aus dem <input> -Tag überschrieben und die anderen Lösungen funktionieren nicht.
Schmidko

1
Diese Antwort ist so wichtig und unglaublich hilfreich. Es ist von entscheidender Bedeutung, sicherzustellen, dass der formDataSchlüsselname mit dem uploadSchlüsselargument übereinstimmt. Es funktioniert jetzt für mich.
Modermo

4

da werden 2 bilder hochgeladen! eine mit Dateierweiterung und eine andere Datei ohne Erweiterung. tmp_path löschen (Datei ohne Erweiterung)

nach dem
src.pipe(dest);

Fügen Sie den folgenden Code hinzu

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


4

Dies für die API könnten Sie verwenden

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

Dies funktioniert auch gut auf Postman verwendet, aber die Datei kommt nicht mit der Erweiterung .jpg irgendwelche Ratschläge? Wie unten kommentiert

Dies ist die Standardfunktion von multer, wenn beim Hochladen einer Datei ohne Erweiterung jedoch das Dateiobjekt bereitgestellt wird, mit dem Sie die Dateierweiterung aktualisieren können.

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

Leider liefert die Fehlermeldung keine eindeutigen Informationen über das eigentliche Problem. Dafür ist ein gewisses Debugging erforderlich.

Aus der Stapelverfolgung ergibt sich der Ursprung des Fehlers im multerPaket:

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

Und die seltsame (möglicherweise fehlerhafte) Übersetzung, die hier angewendet wird, ist die Quelle der Nachricht selbst ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLeftist ein Objekt, das den Namen des Feldes enthält, das Ihr Server erwartet, und file.fieldnamedas den Namen des vom Client bereitgestellten Felds enthält. Der Fehler wird ausgelöst, wenn zwischen dem vom Client angegebenen Feldnamen und dem vom Server erwarteten Feldnamen eine Nichtübereinstimmung besteht.

Die Lösung besteht darin, den Namen entweder auf dem Client oder auf dem Server so zu ändern , dass beide übereinstimmen.

Zum Beispiel bei der Verwendung fetchauf dem Client ...

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

Und der Server hätte eine Route wie die folgende ...

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

Beachten Sie, dass dies myfileder gebräuchliche Name ist (in diesem Beispiel).


Ich danke dir sehr. Ihr Kommentar gab mir einen Hinweis auf meinen Fehler. In meinem Fall hatte ich 2 Formulare in unterschiedlichen Ansichten und unterschiedlichen Router-Dateien. Der erste Router verwendete das Namensfeld mit Ansicht eins und sein Dateiname war "imgLoading". Die zweite Ansicht hatte einen anderen Namen als die Dateieingabe. Aus irgendeinem Grund erlaubt multer nicht, dass Sie in verschiedenen Ansichten unterschiedliche Namen festlegen. Daher habe ich beschlossen, in beiden Ansichten denselben Namen für die Dateieingabe zu verwenden.
Luis Armando

1

Ich löse dieses Problem auf der Suche nach dem Namen, den ich auf meine Anfrage weitergegeben habe

Ich schickte auf Körper:

{thumbbail: <myimg>}

und ich hatte erwartet:

upload.single('thumbnail')

Also korrigiere ich den Namen, den ein Send auf Anfrage sendet


1

Verschiedene Dateinamen , die als „geschrieben recfile “ an <input type="file" name='recfile' placeholder="Select file"/>und erhielten als „ Datei “ auf upload.single('file')

Lösung : Stellen Sie sicher, dass sowohl die gesendete als auch die empfangene Datei ähnlich sindupload.single('recfile')


0

In meinem Szenario geschah dies, weil ich einen Parameter in umbenannt, swagger.yamldie Dokumentenseite jedoch nicht neu geladen habe.

Daher habe ich die API mit einem unerwarteten Eingabeparameter ausprobiert.
Lange Rede kurzer Sinn, F5ist mein Freund.


0

wahrscheinlich geben Sie nicht den gleichen Namen an, den Sie in der upload.single('file').


0

In meinem Fall hatte ich 2 Formulare in unterschiedlichen Ansichten und unterschiedlichen Router-Dateien. Der erste Router verwendete das Namensfeld mit Ansicht eins und sein Dateiname war "inputGroupFile02". Die zweite Ansicht hatte einen anderen Namen für die Dateieingabe. Aus irgendeinem Grund erlaubt Multer nicht, dass Sie in verschiedenen Ansichten unterschiedliche Namen festlegen. Daher habe ich beschlossen, in beiden Ansichten denselben Namen für die Dateieingabe zu verwenden.

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.