Node Multer campo imprevisto


134

Sto lavorando per caricare un file sulla mia app utilizzando il modulo npm multer.

La funzione multer che ho definito è quella di consentire un singolo file caricato nel file system. Tutto funziona durante il runtime; il problema è dopo che ho caricato il file ottengo un errore di seguito. Qualche consiglio apprezzato su dove cercare.

Errore:

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

Risposte:


139

Dobbiamo assicurarci che l'attributo type = file con l'attributo name sia lo stesso del nome del parametro passato 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
Ti dispiacerebbe spiegare perché questo funziona e cosa c'è di diverso? —_____—
IIllIIll

8
Funziona perfettamente come il fascino. Dobbiamo assicurarci che il file type = con l'attributo name sia lo stesso del nome del parametro passato in upload.single ('attr')
Ramki,

1
Il mio caso non funziona. Sto affrontando lo stesso problema. Ma nel mio codice macchina di Windows funziona. Sto riscontrando problemi con il mio MAC. Qualcuno può aiutarmi con questo?
HaRdik Kaji,

6
L'attributo name del tipo = "file" in html deve corrispondere a upload.single ('nome') nel codice del server.
Prasanth Jaya,

Come impostare la richiesta client per un caricamento di più file? Il campo "file" è vuoto.
吳 強 福

219

Quello <NAME>che usi nella upload.single(<NAME>)funzione multer deve essere uguale a quello che usi <input type="file" name="<NAME>" ...>.

Quindi devi cambiare

var type = upload.single('file')

per

var type = upload.single('recfile')

in te app.js

Spero che questo ti aiuti.


2
Sarebbe utile se lo inserissero nel file Leggimi invece di riempirlo con "avatar".
hugos

1
Ma dobbiamo ancora evitare l'eccezione in caso di uso improprio .. come catturare questa eccezione?
syberkitten,

Solo per riferimento, se stai usando curl e il comando è simile al seguente: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Quindi il valore per upload.single è "upload"
chrismarx

19

Un seguito alla risposta di Vincent.

Non è una risposta diretta alla domanda poiché la domanda utilizza un modulo.

Per me, non era il nome del tag di input utilizzato, ma il nome quando si aggiungeva il file a formData.

file front-end

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

file del servizio Web:

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

Questo mi ha salvato la giornata. Grazie. Se si utilizza FormData.append () l'attributo name dal tag <input> verrà sovrascritto e le altre soluzioni non funzioneranno.
Schmidko,

1
Questa risposta è così importante e incredibilmente utile. È formDatafondamentale assicurarsi che il nome della chiave sia lo stesso uploaddell'argomento chiave. Funziona per me adesso.
Modermo,

4

poiché vengono caricate 2 immagini! uno con estensione file e altri file senza estensione. eliminare tmp_path (file senza estensione)

dopo
src.pipe(dest);

aggiungi sotto il codice

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


4

Questo per l'API che potresti usare

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

Funziona bene anche con Postman ma il file non ha estensione .jpg Qualche consiglio? Come commentato di seguito

Questa è la funzione predefinita di Multer se si carica un file senza estensione, tuttavia, viene fornito l'oggetto file, tramite il quale è possibile aggiornare l'estensione del file.

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

Sfortunatamente, il messaggio di errore non fornisce informazioni chiare su quale sia il vero problema. Per questo, è richiesto un po 'di debug.

Dalla traccia dello stack, ecco l'origine dell'errore nel multerpacchetto:

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 la strana (forse errata) traduzione applicata qui è la fonte del messaggio stesso ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLeftè un oggetto che contiene il nome del campo atteso dal server e file.fieldnamecontiene il nome del campo fornito dal client. L'errore viene generato quando si verifica una discrepanza tra il nome del campo fornito dal client e il nome del campo previsto dal server.

La soluzione è cambiare il nome sul client o sul server in modo che i due siano d'accordo.

Ad esempio, quando si utilizza fetchsul client ...

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

E il server avrebbe un percorso come il seguente ...

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

Si noti che myfileè il nome comune (in questo esempio).


Grazie mille. Il tuo commento mi ha dato un suggerimento sul mio errore. Nel mio caso, avevo 2 moduli in viste diverse e file router diversi. Il primo router ha usato il campo nome con la vista uno e il suo nome file era "imgLoading". La seconda vista aveva un altro nome l'input del file. Per qualche motivo il multer non consente di impostare nomi diversi in viste diverse, quindi ho deciso di usare lo stesso nome per l'input del file in entrambe le viste.
Luis Armando il

1

Risolvo questi problemi cercando il nome che ho passato sulla mia richiesta

Stavo spedendo sul corpo:

{thumbbail: <myimg>}

e mi aspettavo di:

upload.single('thumbnail')

così, fisso il nome che un invia su richiesta


1

Nome file diverso che è stato pubblicato come " recfile " in <input type="file" name='recfile' placeholder="Select file"/>e ricevuto come " file " in upload.single('file')

Soluzione : assicurarsi che i file inviati e ricevuti siano similiupload.single('recfile')


0

Nel mio scenario ciò stava accadendo perché ho rinominato un parametro swagger.yamlma non ho ricaricato la pagina dei documenti.

Quindi stavo provando l'API con un parametro di input imprevisto.
Per farla breve, F5è mio amico.


0

probabilmente non stai dando lo stesso nome che hai citato in upload.single('file').


0

Nel mio caso, avevo 2 moduli in viste diverse e file router diversi. Il primo router ha usato il campo nome con la vista uno e il suo nome file era "inputGroupFile02". La seconda vista aveva un altro nome per l'input del file. Per qualche motivo Multer non consente di impostare nomi diversi in viste diverse, quindi ho deciso di utilizzare lo stesso nome per l'input del file in entrambe le viste.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.