Node Multer lĩnh vực bất ngờ


134

Tôi đang làm việc để tải tệp lên ứng dụng của mình bằng mô-đun npm multer.

Hàm multer mà tôi đã xác định là cho phép một tệp được tải lên hệ thống tệp. Tất cả mọi thứ hoạt động trong thời gian chạy; vấn đề là sau khi tôi tải tập tin lên, tôi gặp lỗi bên dưới. Bất kỳ lời khuyên đánh giá cao về nơi để tìm.

Lỗi:

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

Câu trả lời:


139

Chúng ta phải đảm bảo rằng type = file có thuộc tính name phải giống với tên tham số được truyền vào 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
Bạn có thể giải thích lý do tại sao điều này hoạt động và những gì khác nhau? Mạnh___ Khác
IIllIIll

8
Hoạt động hoàn hảo như bùa mê. Chúng tôi phải đảm bảo loại = tệp có thuộc tính name phải giống với tên tham số được truyền trong upload.single ('attr')
Ramki

1
Trường hợp của tôi nó không hoạt động. Tôi đang đối mặt với vấn đề tương tự. Nhưng trong mã máy windows của tôi đang hoạt động. Tôi đang gặp vấn đề với MAC của mình.? Bất cứ ai có thể giúp tôi với điều này?
HaRdik Kaji

6
Thuộc tính name của type = "file" trong html phải khớp với upload.single ('name') trong mã máy chủ.
Prasanth Jaya

Làm cách nào để đặt yêu cầu máy khách cho tải lên nhiều tệp? Trường 'tập tin' trống.
吳 強

219

Hàm <NAME>bạn sử dụng trong upload.single(<NAME>)chức năng của multer phải giống với chức năng bạn sử dụng <input type="file" name="<NAME>" ...>.

Vì vậy, bạn cần phải thay đổi

var type = upload.single('file')

đến

var type = upload.single('recfile')

trong bạn app.js

Hi vọng điêu nay co ich.


2
Sẽ rất hữu ích nếu họ đặt nó trong readme thay vì điền nó vào 'avatar'.
hugos

1
Nhưng chúng ta vẫn cần tránh ngoại lệ trong trường hợp sử dụng sai .. làm thế nào để bắt ngoại lệ này?
syberkitten

Chỉ để tham khảo, nếu bạn đang sử dụng curl và lệnh trông như thế này: curl -v -F upload=@/myfile.txt localhost: 3000 / upload Sau đó, giá trị cho upload.single là "upload"
chrismarx

19

Theo dõi câu trả lời của vincent.

Không phải là một câu trả lời trực tiếp cho câu hỏi vì câu hỏi đang sử dụng một hình thức.

Đối với tôi, đó không phải là tên của thẻ đầu vào đã được sử dụng, mà là tên khi nối thêm tệp vào formData.

tập tin mặt trước

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

tập tin dịch vụ web:

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

Điều này đã cứu ngày của tôi. Cảm ơn bạn. Nếu bạn sử dụng FormData.append (), tên thuộc tính từ thẻ <input> sẽ bị ghi đè và làm cho các giải pháp khác không hoạt động.
Schmidko

1
Câu trả lời này rất quan trọng và vô cùng hữu ích. Đảm bảo rằng formDatatên khóa giống với uploadđối số khóa là rất quan trọng. Nó làm việc cho tôi bây giờ.
Modermo

4

kể từ khi 2 hình ảnh được tải lên! một với phần mở rộng tập tin và tập tin khác mà không cần gia hạn. để xóa tmp_path (tệp không có phần mở rộng)

sau
src.pipe(dest);

thêm mã dưới đây

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


4

Cái này cho Api bạn có thể sử dụng

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

Điều này cũng hoạt động tốt được sử dụng trên Postman nhưng tệp không đi kèm với phần mở rộng .jpg có lời khuyên nào không? Như bình luận bên dưới

Đây là tính năng mặc định của multer nếu tải lên tệp không có phần mở rộng, tuy nhiên, cung cấp cho bạn đối tượng tệp, bằng cách sử dụng mà bạn có thể cập nhật phần mở rộng của tệp.

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

Thật không may, thông báo lỗi không cung cấp thông tin rõ ràng về vấn đề thực sự là gì. Đối với điều đó, một số gỡ lỗi là cần thiết.

Từ dấu vết ngăn xếp, đây là nguồn gốc của lỗi trong multergói:

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

Và bản dịch lạ (có thể bị nhầm) được áp dụng ở đây là nguồn gốc của thông điệp ...

'LIMIT_UNEXPECTED_FILE': 'Unexpected field'

filesLeftlà một đối tượng chứa tên của trường mà máy chủ của bạn đang mong đợi và file.fieldnamechứa tên của trường được cung cấp bởi máy khách. Lỗi được đưa ra khi có sự không khớp giữa tên trường được cung cấp bởi máy khách và tên trường mà máy chủ mong đợi.

Giải pháp là thay đổi tên trên máy khách hoặc máy chủ để hai người đồng ý.

Ví dụ: khi sử dụng fetchtrên máy khách ...

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

Và máy chủ sẽ có một lộ trình như sau ...

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

Lưu ý rằng đó là myfiletên phổ biến (trong ví dụ này).


Cảm ơn bạn rất nhiều. Nhận xét của bạn đã cho tôi một gợi ý về lỗi của tôi. Trong trường hợp của tôi, tôi có 2 biểu mẫu ở dạng xem khác nhau và tệp bộ định tuyến khác nhau. Bộ định tuyến đầu tiên sử dụng trường tên với chế độ xem một và tên tệp của nó là "imgLoading". Khung nhìn thứ hai có tên khác là đầu vào tập tin. Vì một số lý do, multer không cho phép bạn đặt tên khác nhau trong các chế độ xem khác nhau, vì vậy tôi đã sử dụng cùng tên cho đầu vào tệp trong cả hai chế độ xem.
Luis Armando

1

Tôi giải quyết vấn đề này để tìm kiếm tên mà tôi đã chuyển theo yêu cầu của tôi

Tôi đã gửi trên cơ thể:

{thumbbail: <myimg>}

và tôi đã mong đợi:

upload.single('thumbnail')

vì vậy, tôi sửa tên mà gửi theo yêu cầu


1

Tên tệp khác nhau được đăng dưới dạng " recfile " tại <input type="file" name='recfile' placeholder="Select file"/>và nhận dưới dạng " tệp " tại upload.single('file')

Giải pháp : đảm bảo cả tệp đã gửi và nhận đều giống nhauupload.single('recfile')


0

Trong kịch bản của tôi, điều này đã xảy ra vì tôi đã đổi tên một tham số trong swagger.yamlnhưng không tải lại trang tài liệu.

Do đó tôi đã thử API với tham số đầu vào không mong muốn.
Câu chuyện dài, F5là bạn của tôi.


0

có lẽ bạn không đặt tên giống như bạn đã đề cập trong upload.single('file').


0

Trong trường hợp của tôi, tôi có 2 biểu mẫu ở dạng xem khác nhau và tệp bộ định tuyến khác nhau. Bộ định tuyến đầu tiên đã sử dụng trường tên với chế độ xem một và tên tệp của nó là "inputgroupFile02". Khung nhìn thứ hai có một tên khác cho đầu vào tập tin. Vì một số lý do, Multer không cho phép bạn đặt tên của người khác trong các chế độ xem khác nhau, vì vậy tôi đã quyết định sử dụng cùng tên cho mục nhập tệp trong cả hai chế độ xem.

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.