Несподіване поле Вузла Мультера


134

Я працюю над завантаженням файлу у свою програму за допомогою модуля multer npm.

Функція мультирування, яку я визначила, полягає в тому, щоб дозволити один файл, завантажений у файлову систему. Все працює під час роботи; проблема полягає в тому, що коли я завантажую файл, я отримую помилку нижче. Будь-яка порада оцінена, де шукати.

Помилка:

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

Відповіді:


139

Ми повинні переконатися, що type = файл з атрибутом name повинен бути таким самим, як ім'я параметра, передане в 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
Ви не проти пояснити, чому це працює і чим відрізняється? —_____—
IIllIIll

8
Працює чудово, як шарм. Ми повинні переконатися, що тип = файл з атрибутом name має бути таким самим, як ім'я параметра, переданого в upload.single ('attr')
Рамкі,

1
У моєму випадку це не працює. Я зіткнувся з тим же питанням. Але в моєму Windows працює машинний код. У мене є проблеми з моїм MAC.? Хтось може допомогти зі мною в цьому?
HaRdik Kaji

6
Атрибут імені типу = "файл" в html повинен відповідати upload.single ("ім'я") в коді сервера.
Прасант Джая

Як встановити запит клієнта на завантаження декількох файлів? Поле "файли" порожнє.
吳 強 福

219

Функція, яку <NAME>ви використовуєте в upload.single(<NAME>)функції мультера, повинна бути такою ж, як і в якій ви використовуєте <input type="file" name="<NAME>" ...>.

Тому потрібно змінити

var type = upload.single('file')

до

var type = upload.single('recfile')

у вашому app.js

Сподіваюся, це допомагає.


2
Це допоможе, якщо вони помістять це в readme замість того, щоб заповнити його "avatar".
hugos

1
Але нам все одно потрібно уникати винятку у разі неправильного використання .. як зловити цей виняток?
syberkitten

Для довідки, якщо ви використовуєте curl, і команда виглядає приблизно так: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Тоді значення для upload.single - "upload"
chrismarx

19

Продовження відповіді Вінсента.

Не пряма відповідь на питання, оскільки для запитання використовується форма.

Для мене це було не ім'ям вхідного тегу, який використовувався, а ім'ям при додаванні файлу до formData.

файл переднього кінця

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

файл веб-служби:

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

Це врятувало мені день. Дякую. Якщо ви використовуєте FormData.append (), ім'я attribut з тегу <input> буде перезаписано, і інші рішення не працюватимуть.
Шмідько

1
Ця відповідь настільки важлива і неймовірно корисна. Переконайтесь, що formDataключове ім’я є таким самим, як uploadключовий аргумент, є вирішальним. Це працює для мене зараз.
Модермо

4

оскільки завантажуються 2 зображення! один з розширенням файлу та інший файл без розширення. видалити tmp_path (файл без розширення)

після
src.pipe(dest);

додати код нижче

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


4

Це для Api, який ви можете використовувати

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

Це також добре працює на Postman, але файл не постачається з розширенням .jpg будь-якими порадами? Як коментується нижче

Це за замовчуванням функція мультера, якщо завантажує файл без розширення, однак надає вам об’єкт файлу, за допомогою якого ви можете оновити розширення файлу.

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

На жаль, повідомлення про помилку не дає чіткої інформації про те, що є справжньою проблемою. Для цього потрібна деяка налагодження.

З сліду стека, ось джерело помилки в multerпакеті:

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

І дивний (можливо, помилковий) переклад, застосований тут, є джерелом самого повідомлення ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLeft- це об'єкт, який містить ім'я поля, яке очікує ваш сервер, і file.fieldnameмістить ім'я поля, надане клієнтом. Помилка видається, коли є невідповідність між іменем поля, наданим клієнтом, та іменем поля, очікуваним сервером.

Рішення полягає в зміні імені або на клієнті, або на сервері щоб вони погодилися.

Наприклад, при використанні fetchна клієнті ...

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

І сервер мав би такий маршрут, як наступний ...

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

Зауважте, що це саме myfileзагальна назва (у цьому прикладі).


Дуже дякую. Ваш коментар дав мені підказку про мою помилку. У моєму випадку у мене було 2 форми в різних видах і файлах маршрутизатора. Перший маршрутизатор використовував поле імені для перегляду одного і його ім'я файлу було "imgLoading". Другий вигляд мав іншу назву введення файлу. Чомусь multer не дозволяє встановити диференційоване ім'я в різних видах, тому я вирішив використовувати одне і те ж ім'я для введення файлу в обох видах.
Луїс Армандо

1

Я вирішую ці питання, шукаючи ім’я, яке я передав на моє прохання

Я надсилав по тілу:

{thumbbail: <myimg>}

і я очікував:

upload.single('thumbnail')

таким чином, я фіксую ім'я, яке надсилається за запитом


1

Різне ім'я файлу, яке розміщено як " recfile " у <input type="file" name='recfile' placeholder="Select file"/>та отримано як " файл " у upload.single('file')

Рішення : переконайтеся, що і надісланий, і отриманий файл схожіupload.single('recfile')


0

У моєму сценарії це сталося тому, що я перейменував параметр у, swagger.yamlале не перезавантажив сторінку документів.

Отже, я намагався API з несподіваним вхідним параметром.
Коротка історія, F5мій друг.



0

У моєму випадку у мене було 2 форми в різних видах і файлах маршрутизатора. Перший маршрутизатор використовував поле імені для перегляду одного, а його ім'я було "inputGroupFile02". Другий вигляд мав іншу назву для введення файлів. Чомусь Multer не дозволяє встановлювати ім'я різниці в різних представленнях, тому я вирішив використовувати те саме ім'я для введення файлу в обох видах.

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.