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

คำตอบ:


141

เราต้องตรวจสอบให้แน่ใจว่าแอตทริบิวต์ type = file with 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
ทำงานได้อย่างสมบูรณ์แบบเหมือนมีเสน่ห์เราต้องตรวจสอบให้แน่ใจว่าแอตทริบิวต์ type = file with name ควรจะเหมือนกับชื่อพารามิเตอร์ที่ส่งผ่านใน upload.single ('attr')
Ramki

1
กรณีของฉันมันไม่ทำงาน ฉันกำลังประสบปัญหาเดียวกัน แต่ในรหัสเครื่อง windows ของฉันใช้งานได้ ฉันมีปัญหากับ MAC ของฉัน? ใครสามารถช่วยฉันได้บ้าง
HaRdik Kaji

6
แอตทริบิวต์ name ของ type = "file" ใน html ควรตรงกับ upload.single ('name') ในรหัสเซิร์ฟเวอร์
Prasanth Jaya

จะตั้งค่าคำขอของลูกค้าสำหรับการอัปโหลดหลายไฟล์ได้อย่างไร? ฟิลด์ "files" ว่างเปล่า
吳強福

219

<NAME>คุณใช้ใน multer ของฟังก์ชั่นจะต้องเป็นแบบเดียวกันกับที่คุณใช้ใน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

ติดตามคำตอบของ Vincent

ไม่ใช่คำตอบโดยตรงสำหรับคำถามเนื่องจากคำถามใช้แบบฟอร์ม

สำหรับฉันมันไม่ใช่ชื่อของแท็กอินพุตที่ใช้ แต่เป็นชื่อเมื่อผนวกไฟล์เข้ากับ formData

ไฟล์ส่วนหน้า

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

ไฟล์บริการเว็บ:

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

วันนี้ช่วยฉันไว้ ขอบคุณ. หากคุณใช้ FormData.append () แอตทริบิวต์ชื่อจากแท็ก <input> จะถูกเขียนทับและทำให้โซลูชันอื่นไม่ทำงาน
Schmidko

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

นอกจากนี้ยังใช้งานได้ดีกับบุรุษไปรษณีย์ แต่ไฟล์ไม่มาพร้อมกับนามสกุล. 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 รูปแบบในมุมมองที่แตกต่างกันและไฟล์เราเตอร์ differents เราเตอร์ตัวแรกใช้ฟิลด์ชื่อกับมุมมองหนึ่งและชื่อไฟล์คือ "imgLoading" มุมมองที่สองมีชื่ออื่นสำหรับการป้อนไฟล์ ด้วยเหตุผลบางประการ Multer ไม่อนุญาตให้คุณตั้งชื่อที่แตกต่างกันในมุมมองที่แตกต่างกันดังนั้นฉันจึงตัดสินใจใช้ชื่อเดียวกันสำหรับการป้อนไฟล์ในทั้งสองมุมมอง
Luis Armando

1

ฉันแก้ปัญหานี้โดยมองหาชื่อที่ฉันส่งต่อตามคำขอของฉัน

ฉันกำลังส่งร่างกาย:

{thumbbail: <myimg>}

และฉันคาดหวังว่าจะ:

upload.single('thumbnail')

ดังนั้นฉันจึงแก้ไขชื่อที่ส่งตามคำขอ


1

ชื่อไฟล์ที่แตกต่างกันซึ่งโพสต์เป็น " recfile " ที่<input type="file" name='recfile' placeholder="Select file"/>และรับเป็น " file " ที่ upload.single('file')

วิธีแก้ไข : ตรวจสอบให้แน่ใจว่าทั้งไฟล์ที่ส่งและรับนั้นเหมือนกันupload.single('recfile')


0

ในสถานการณ์ของฉันสิ่งนี้เกิดขึ้นเนื่องจากฉันเปลี่ยนชื่อพารามิเตอร์ในswagger.yamlแต่ไม่ได้โหลดหน้าเอกสารซ้ำ

ดังนั้นฉันจึงลองใช้ API ด้วยพารามิเตอร์อินพุตที่ไม่คาดคิด
เรื่องสั้นสั้นF5เป็นเพื่อนของฉัน



0

ในกรณีของฉันฉันมี 2 รูปแบบในมุมมองที่แตกต่างกันและไฟล์เราเตอร์ differents เราเตอร์ตัวแรกใช้ฟิลด์ชื่อกับมุมมองหนึ่งและชื่อไฟล์คือ "inputGroupFile02" มุมมองที่สองมีชื่ออื่นสำหรับการป้อนไฟล์ ด้วยเหตุผลบางอย่าง Multer ไม่อนุญาตให้คุณตั้งชื่อ differents ในมุมมองที่แตกต่างกันดังนั้นฉันจึงตัดสินใจใช้ชื่อเดียวกันสำหรับการป้อนไฟล์ในทั้งสองมุมมอง

ป้อนคำอธิบายภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.