使用Express 4.0上传文件:req.files未定义


239

我试图得到一个简单的文件上传机制的工作与快车4.0,但我不断收到undefinedreq.filesapp.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'); 
}); 

..和随附的帕格代码:

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
ithink可以执行app.post('/ fileupload',busboy(),function(req,res){
Shimon Doodkin 2014年

好的解决方案,我只想指出,您必须./files/在应用程序的主目录中创建目录,否则上传后会出现错误。

临时文件如何处理?busboy是否会自动删除它们?我只是看不到任何临时文件在保存到磁盘之前被删除。
ed-ta

Answers:


210

body-parser模块仅处理JSON和urlencoded表单提交,而不是多部分提交(如果您正在上传文件,情况就是如此)。

对于multipart,您需要使用诸如connect-busboyor multerconnect-multiparty(multiparty / formidable是Express bodyParser中间件中最初使用的东西)之类的东西。同样是FWIW,我正在叫busboy的顶层上工作reformed。它带有Express中间件,也可以单独使用。


4
谢谢,那行得通。虽然我不得不使用connect-busboy而不是仅仅busboy。使用解决方案更新了我的原始帖子。
safwanc 2014年

4
谢了哥们!我找到了connect-multiparty最好的选择!
neciu

reformed仍在开发中?您对github的最后一次提交是在2014年...顺便说一下,您认为处理多部分表单数据的最佳模块是什么?“最好”是指得到最好的支持,并且工作得更好(错误更少),功能更多且拥有更长的未来。.我之所以选择multer它是因为它似乎得到了最好的支持,但我仍然认为应该得到更多的支持。
nbro 2015年

[编辑:没关系,请看下面的答案。]在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 '02

3
你没用fileupload吗?
BrandonFlynn-NB

5
为了使上述答案起作用,您需要在主行中添加这两行app.js const fileUpload = require('express-fileupload') app.use(fileUpload())
Abhishake

11

似乎body-parser 确实支持在Express 3中上传文件,但是当Express 4 不再包含Connect作为依赖项时,对Express 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-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' } }

8

1)确保您的文件确实是从客户端发送的。例如,您可以在Chrome控制台中检查它: 屏幕截图

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提供给我们。

安装机:- 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功能DID甚至不会运行一次。因为我必须包括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 看起来是当今唯一仍然有效的中间件。

在相同的示例中,multerconnect-multiparty给出了req.filereq.files的未定义值,但是express-fileupload可以工作。

关于req.file / req.files的空值,存在很多问题。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.