Загрузка файла с помощью Express 4.0: req.files не определено

239

Я пытаюсь получить простую загрузку файла механизм работать с Express 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');
        });
    });
});
safwanc
источник
1
как это работает с несколькими файлами?
Чови
@chovy это должно работать отлично с несколькими файлами
mscdex
2
я думаю, что это можно сделать app.post ('/ fileupload', busboy (), function (req, res) {
Шимон Дудкин
Хорошее решение Я просто хотел отметить, что вы должны создать ./files/каталог в домашнем каталоге вашего приложения, в противном случае вы получите ошибку после загрузки.
соус
Как обрабатываются временные файлы? Busboy удаляет их автоматически? Я просто нигде не вижу временных файлов, удаляемых перед сохранением на диск.
Эд-та

Ответы:

210

body-parserМодуль обрабатывает только JSON и urlencoded формы представления, не многослойный (что было бы в случае , если вы загружаете файлы).

Для multipart вам нужно использовать что-то вроде connect-busboyили multerили connect-multiparty(multiparty / formidable - это то, что изначально использовалось в промежуточном программном обеспечении Express bodyParser). Также FWIW, я работаю над еще более высокоуровневым слоем поверх busboy колла reformed. Он поставляется с промежуточным программным обеспечением Express, а также может использоваться отдельно.

MSCDEX
источник
4
Спасибо, что сработало. Хотя я должен был использовать connect-busboyвместо просто busboy. Обновил мой оригинальный пост с решением.
safwanc
4
Спасибо друг! Я считаю connect-multipartyвариант лучшим из этих!
neciu
Все reformedеще в разработке? Ваш последний коммит на github - с 2014 года ... Кстати, по вашему мнению, какой модуль лучше всего обрабатывает данные из нескольких частей? Под «лучшим» я подразумеваю лучшую поддерживаемую и ту, которая работает лучше (с меньшим количеством ошибок), с большим количеством функций и с более длинным будущим. Я выбрал, multerпотому что это казалось наилучшей поддержкой, но я все еще думаю, что он должен быть более поддерживаемым.
nbro
[РЕДАКТИРОВАТЬ: все в порядке, только что видел ответ ниже.] Сделал multipart с в Express 3.0, а затем сломался в 4.0? Я спрашиваю, потому что этот учебник использует 3.4.8 и может загружать файлы без необходимости какого-либо дополнительного промежуточного программного обеспечения blog.robertonodi.me/simple-image-upload-with-express
thetrystero
@thetrystero В репозитории github для того конкретного примера, с которым вы ссылались, на самом деле проверены зависимости в репо. Если вы покопаетесь в этих зависимостях, то увидите, что Express 3.x включен, а также Connect 2.x (в который все еще был включен многокомпонентный модуль). Вот почему многочастная обработка работала «из коробки».
mscdex
31

Вот что я нашел, погуглив:

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())
текст
11

Похоже, body-parser он поддерживал загрузку файлов в Express 3, но поддержка Express 4 была прекращена, когда он больше не включал Connect в качестве зависимости

Просматривая некоторые из модулей в ответе 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-Busboy (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' } }
HPierce
источник
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 - это промежуточное ПО, которое волшебным образом обрабатывает «multipart / form-data» и делает загруженные файлы и данные форм доступными для нас в запросе как 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
});

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

Парт Равал
источник
2

Пожалуйста, используйте ниже код

app.use(fileUpload());
Гаурав Кумар
источник
var fileupload = require ("express-fileupload"); app.use (FileUpload ());
Саураб Агарвал
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 .

TRD
источник