Неожиданное поле Node Multer


134

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

Определенная мною функция multer позволяет загружать один файл в файловую систему. Во время работы все работает; проблема в том, что после загрузки файла я получаю сообщение об ошибке ниже. Приветствуются любые советы о том, где искать.

Ошибка:

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

Ответы:


140

Мы должны убедиться, что type = file с атрибутом 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
Не могли бы вы объяснить, почему это работает и в чем отличие? —_____—
IIIIIll 01

8
Работает отлично как charm. Мы должны убедиться, что type = file с атрибутом name должен быть таким же, как имя параметра, переданное в upload.single ('attr')
Ramki

1
Мой случай не работает. Я сталкиваюсь с той же проблемой. Но в моем машинном коде Windows работает. У меня проблемы с моим MAC.? Может ли кто-нибудь помочь мне в этом?
HaRdik Kaji 02

6
Атрибут name типа = "file" в html должен совпадать с upload.single ('name') в коде сервера.
Prasanth Jaya

Как настроить запрос клиента на загрузку нескольких файлов? Поле "файлы" пусто.
吳 強 福

219

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

Итак, вам нужно изменить

var type = upload.single('file')

в

var type = upload.single('recfile')

в тебе app.js

Надеюсь это поможет.


2
Было бы полезно, если бы они поместили это в readme вместо того, чтобы заполнять его «аватаром».
hugos 02

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 (), атрибут имени из тега <input> будет перезаписан, и другие решения не будут работать.
Шмидко

1
Этот ответ очень важен и невероятно полезен. Очень важно убедиться, что formDataимя ключа совпадает с uploadключевым аргументом. Это работает для меня сейчас.
Modermo

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. Как прокомментировано ниже

Это функция Multer по умолчанию, если загружает файл без расширения, однако предоставляет вам объект файла, с помощью которого вы можете обновить расширение файла.

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». Второй вид имел другое имя файла input. По какой-то причине 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.