การอัปโหลดไฟล์ด้วย Express 4.0: req.files ไม่ได้กำหนด


239

ฉันพยายามที่จะได้รับกลไกการอัพโหลดไฟล์ง่ายทำงานกับเอ็กซ์เพรส 4.0 แต่ฉันได้รับ แต่undefinedสำหรับreq.filesในapp.postร่างกาย นี่คือรหัสที่เกี่ยวข้อง:

var bodyParser = require('body-parser');
var methodOverride = require('method-override');
//...
app.use(bodyParser({ uploadDir: path.join(__dirname, 'files'), keepExtensions: true })); 
app.use(methodOverride()); 
//...
app.post('/fileupload', function (req, res) {
  console.log(req.files); 
  res.send('ok'); 
}); 

.. และรหัส Pug ที่มาพร้อมกับ:

form(name="uploader", action="/fileupload", method="post", enctype="multipart/form-data")
    input(type="file", name="file", id="file")
    input(type="submit", value="Upload")

การแก้ปัญหา
ด้วยการตอบสนองโดยmscdexด้านล่างฉันได้เปลี่ยนมาใช้busboyแทนbodyParser:

var fs = require('fs');
var busboy = require('connect-busboy');
//...
app.use(busboy()); 
//...
app.post('/fileupload', function(req, res) {
    var fstream;
    req.pipe(req.busboy);
    req.busboy.on('file', function (fieldname, file, filename) {
        console.log("Uploading: " + filename); 
        fstream = fs.createWriteStream(__dirname + '/files/' + filename);
        file.pipe(fstream);
        fstream.on('close', function () {
            res.redirect('back');
        });
    });
});

1
มันทำงานกับไฟล์หลาย ๆ ไฟล์ได้อย่างไร?
chovy

@chovy มันควรจะทำงานได้ดีกับไฟล์หลายไฟล์
mscdex

2
คิดว่าเป็นไปได้ที่จะทำ app.post ('/ fileupload', busboy (), ฟังก์ชั่น (req, res) {
Shimon Doodkin

ทางออกที่ดีฉันต้องการทราบว่าคุณต้องสร้าง./files/ไดเรกทอรีในโฮมไดเรกทอรีของแอพไม่เช่นนั้นคุณจะได้รับข้อผิดพลาดหลังจากอัปโหลด
ซอส

มีการจัดการไฟล์อุณหภูมิอย่างไร busboy ลบโดยอัตโนมัติหรือไม่? ฉันไม่เห็นไฟล์ชั่วคราวที่ถูกลบก่อนบันทึกลงดิสก์
ed-ta

คำตอบ:


210

body-parserโมดูลเท่านั้นจัดการ JSON และส่งแบบฟอร์ม urlencoded ไม่ multipart (ซึ่งจะเป็นกรณีที่ถ้าคุณกำลังอัปโหลดไฟล์)

สำหรับ multipart คุณจะต้องใช้สิ่งที่ชอบconnect-busboyหรือmulterหรือconnect-multiparty(multiparty / formidable คือสิ่งที่เคยใช้ในมิดเดิลแวร์ด่วน bodyParser) นอกจากนี้ยัง FWIW reformedผมทำงานในชั้นระดับที่สูงขึ้นด้านบนของบริกรที่เรียกว่า มันมาพร้อมกับมิดเดิลแวร์ Express และยังสามารถใช้แยกกันได้


4
ขอบคุณที่ทำงาน ถึงแม้ว่าผมจะมีการใช้แทนเพียงconnect-busboy busboyอัปเดตโพสต์ดั้งเดิมของฉันด้วยโซลูชัน
safwanc

4
ขอบคุณเพื่อน! ฉันพบconnect-multipartyตัวเลือกที่ดีที่สุดของสิ่งเหล่านี้!
neciu

คือreformedยังอยู่ภายใต้การพัฒนา? ความมุ่งมั่นล่าสุดของคุณเกี่ยวกับ GitHub มาจากปี 2014 ... ตามความเห็นของคุณโมดูลที่ดีที่สุดในการจัดการข้อมูลแบบฟอร์มหลายส่วนคืออะไร? โดย "ดีที่สุด" ฉันหมายถึงการสนับสนุนที่ดีที่สุดและสิ่งที่ทำงานได้ดีขึ้น (ข้อผิดพลาดน้อยลง) มีคุณสมบัติมากขึ้นและมีอนาคตที่ยาวนานขึ้นฉันเลือกmulterเพราะดูเหมือนว่าได้รับการสนับสนุนที่ดีที่สุด แต่ฉันคิดว่าควรได้รับการสนับสนุนมากกว่า
nbro

[แก้ไข: ไม่เป็นไรเพิ่งเห็นคำตอบด้านล่าง] มีหลายส่วนพร้อมด้วย express 3.0 แล้วหักใน 4.0? ฉันถามเพราะบทช่วยสอนนี้ใช้ 3.4.8 และสามารถอัปโหลดไฟล์ได้โดยไม่จำเป็นต้องมีมิดเดิลแวร์พิเศษใด ๆblog.robertonodi.me/simple-image-upload-with-express
thetrystero

@thetrystero repo github สำหรับตัวอย่างเฉพาะที่คุณเชื่อมโยงกับที่จริงมีการอ้างอิงตรวจสอบใน repo หากคุณขุดผ่านการพึ่งพาเหล่านั้นคุณจะเห็น Express 3.x รวมอยู่ด้วยรวมถึง Connect 2.x (ซึ่งยังมีโมดูลหลายส่วนที่มาพร้อมกับมัน) นั่นคือเหตุผลที่การจัดการหลายส่วนกำลังทำงาน "นอกกรอบ"
mscdex

31

นี่คือสิ่งที่ฉันพบ googling รอบ ๆ :

var fileupload = require("express-fileupload");
app.use(fileupload());

ซึ่งเป็นกลไกที่ง่ายมากสำหรับการอัพโหลด

app.post("/upload", function(req, res)
{
    var file;

    if(!req.files)
    {
        res.send("File was not found");
        return;
    }

    file = req.files.FormFieldName;  // here is the field name of the form

    res.send("File Uploaded");


});

ช้าเกินไปสำหรับไฟล์ขนาดใหญ่
Eduardo

3
คุณไม่ได้ใช้fileuploadเหรอ?
BrandonFlynn-NB

5
สำหรับคำตอบข้างต้นในการทำงานคุณต้องเพิ่มสองบรรทัดนี้ในหน้าหลักของคุณapp.js const fileUpload = require('express-fileupload') app.use(fileUpload())
abhishake

11

ดูเหมือนว่าbody-parser ได้อัปโหลดไฟล์การสนับสนุนในการด่วน 3 แต่การสนับสนุนถูกทิ้งด่วน 4 เมื่อมันไม่ได้รวมถึงการเชื่อมต่อเป็นพึ่งพา

หลังจากตรวจสอบบางส่วนของโมดูลในคำตอบของ mscdex ฉันพบว่าexpress-busboyมันเป็นทางเลือกที่ดีกว่าและเป็นสิ่งที่ใกล้เคียงที่สุดสำหรับการแทนที่แบบดรอปอิน ข้อแตกต่างที่ฉันสังเกตเห็นคือคุณสมบัติของไฟล์ที่อัปโหลด

console.log(req.files)ใช้body-parser (Express 3) เอาท์พุทวัตถุที่มีลักษณะดังนี้:

{ file: 
   { fieldName: 'file',
     originalFilename: '360px-Cute_Monkey_cropped.jpg',
     name: '360px-Cute_Monkey_cropped.jpg'
     path: 'uploads/6323-16v7rc.jpg',
     type: 'image/jpeg',
     headers: 
      { 'content-disposition': 'form-data; name="file"; filename="360px-Cute_Monkey_cropped.jpg"',
        'content-type': 'image/jpeg' },
     ws: 
      WriteStream { /* ... */ },
     size: 48614 } }

เปรียบเทียบกับการconsole.log(req.files)ใช้รถด่วนพิเศษ (Express 4):

{ file: 
   { field: 'file',
     filename: '360px-Cute_Monkey_cropped.jpg',
     file: 'uploads/9749a8b6-f9cc-40a9-86f1-337a46e16e44/file/360px-Cute_Monkey_cropped.jpg',
     mimetype: 'image/jpeg',
     encoding: '7bit',
     truncated: false
     uuid: '9749a8b6-f9cc-40a9-86f1-337a46e16e44' } }

8

1) ตรวจสอบให้แน่ใจว่าไฟล์ของคุณถูกส่งจากฝั่งไคลเอ็นต์จริงๆ ตัวอย่างเช่นคุณสามารถตรวจสอบได้ใน Chrome Console: ภาพหน้าจอ

2) นี่คือตัวอย่างพื้นฐานของ NodeJS แบ็กเอนด์:

const express = require('express');
const fileUpload = require('express-fileupload');
const app = express();

app.use(fileUpload()); // Don't forget this line!

app.post('/upload', function(req, res) {
   console.log(req.files);
   res.send('UPLOADED!!!');
});

7

multerเป็นมิดเดิลแวร์ที่จัดการ“ หลายส่วน / แบบฟอร์มข้อมูล” และอย่างน่าอัศจรรย์ & ทำให้ไฟล์ที่อัปโหลดและข้อมูลแบบฟอร์มพร้อมให้เราตามที่ร้องขอในฐานะ request.files และ request.body

ติดตั้ง multer: - npm install multer --save

ในไฟล์. html: -

<form method="post" enctype="multipart/form-data" action="/upload">
    <input type="hidden" name="msgtype" value="2"/>
    <input type="file" name="avatar" />
    <input type="submit" value="Upload" />
</form>

ในไฟล์. js: -

var express = require('express');
var multer = require('multer');
var app = express();
var server = require('http').createServer(app);
var port = process.env.PORT || 3000;
var upload = multer({ dest: 'uploads/' });

app.use(function (req, res, next) {
  console.log(req.files); // JSON Object
  next();
});

server.listen(port, function () {
  console.log('Server successfully running at:-', port);
});

app.get('/', function(req, res) {
  res.sendFile(__dirname + '/public/file-upload.html');
})

app.post('/upload', upload.single('avatar'),  function(req, res) {
  console.log(req.files); // JSON Object
});

หวังว่านี่จะช่วยได้!



0

แก้ไขปัญหา !!!!!!!

เปลี่ยนจากstorageฟังก์ชั่นไม่ได้วิ่งแม้แต่ครั้งเดียว เพราะฉันต้องรวมapp.use(upload)เป็นupload = multer({storage}).single('file');

 let storage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, './storage')
          },
          filename: function (req, file, cb) {
            console.log(file) // this didn't print anything out so i assumed it was never excuted
            cb(null, file.fieldname + '-' + Date.now())
          }
    });

    const upload = multer({storage}).single('file');

-1

express-fileupload ดูเหมือนว่ามิดเดิลแวร์เดียวเท่านั้นที่ยังคงใช้งานได้ในปัจจุบัน

ด้วยตัวอย่างเดียวกันmulterและconnect-multipartyให้ค่าreq.fileหรือreq.files ที่ไม่ได้กำหนดแต่ใช้express-fileuploadงานได้

และมีจำนวนมากที่มีคำถามและประเด็นเกี่ยวกับค่าว่างของreq.file / req.files

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