使用 Express 4.0 上传文件:req.files undefined

Posted

技术标签:

【中文标题】使用 Express 4.0 上传文件:req.files undefined【英文标题】:File uploading with Express 4.0: req.files undefined 【发布时间】:2014-05-31 14:48:35 【问题描述】:

我正在尝试获得一个与 Express 4.0 一起使用的简单文件上传机制,但我在 app.post 正文中不断收到req.filesundefined。以下是相关代码:

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');
        );
    );
);

【问题讨论】:

如何处理多个文件? @chovy 它应该适用于多个文件 我认为可以做 app.post('/fileupload',busboy(), function(req, res) 很好的解决方案我只想注意,您必须在应用的主目录中创建一个./files/ 目录,否则上传后会出现错误。 临时文件是如何处理的? busboy 会自动删除它们吗?在保存到磁盘之前,我只是没有看到任何临时文件被删除。 【参考方案1】:

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

对于多部分,您需要使用类似 connect-busboymulterconnect-multiparty 的东西(multiparty/formidable 是最初在 express bodyParser 中间件中使用的)。同样是 FWIW,我正在 busboy 之上的更高级别的层上工作,称为 reformed。自带Express中间件,也可以单独使用。

【讨论】:

谢谢,成功了。虽然我不得不使用connect-busboy 而不仅仅是busboy。用解决方案更新了我原来的帖子。 谢谢伙计!我发现connect-multiparty 选项最好! reformed 还在开发中吗?您在 github 上的最后一次提交是从 2014 年开始......顺便说一下,在您看来,处理多部分表单数据的最佳模块是什么?我所说的“最佳”是指最好的支持和更好的工作(更少的错误),具有更多的功能和更长的未来。我选择multer,因为它似乎是最好的支持,但我仍然认为它应该更多支持。 [编辑:没关系,刚刚看到下面的答案。] 在 express 3.0 中使用 multipart,然后在 4.0 中中断?我问是因为本教程使用 3.4.8 并且可以上传文件而不需要任何额外的中间件blog.robertonodi.me/simple-image-upload-with-express @thetrystero 您链接到的特定示例的 github 存储库实际上已将依赖项签入存储库。如果您深入研究这些依赖项,您将看到 Express 3.x 以及 Connect 2.x(它仍然捆绑了一个多部分模块)。这就是为什么多部分处理“开箱即用”的原因。【参考方案2】:

这是我在谷歌上搜索的结果:

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


);

【讨论】:

对于大文件来说太慢了【参考方案3】:

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

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!!!');
);

【讨论】:

【参考方案4】:

看起来body-parser确实支持在 Express 3 中上传文件,但在 no longer included Connect as a dependency

时放弃了对 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  

与使用 express-busboy(Express 4)的console.log(req.files) 相比:

 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'  

【讨论】:

【参考方案5】:

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

希望这会有所帮助!

【讨论】:

【参考方案6】:

请使用下面的代码

app.use(fileUpload());

【讨论】:

var fileupload = require("express-fileupload"); app.use(fileupload());【参考方案7】:

此功能需要安装包,其中有很多,但我个人更喜欢“express-fileupload”。只需在终端中通过“npm i express-fileupload”命令安装它,然后在你的根文件中使用它

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

【讨论】:

【参考方案8】:

问题已解决!!!!!!!

原来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');

【讨论】:

【参考方案9】:

只是为了添加到上面的答案,您可以将 express-fileupload 的使用简化为仅需要它的单个路由,而不是将其添加到每个路由。

let fileupload = require("express-fileupload");

...

app.post("/upload", fileupload, function(req, res)

...

);

【讨论】:

【参考方案10】:

我在 methodOverride 中间件之前添加了 multer 作为全局中间件, 它也可以在 router.put 中使用。

const upload = multer(
    storage: storage
).single('featuredImage');
app.use(upload);

app.use(methodOverride(function (req, res) 
  ...
));

【讨论】:

【参考方案11】:

强大的:

const formidable = require('formidable');

app.post('/api/upload', (req, res, next) => 
  const form = formidable( multiples: true );

  form.parse(req, (err, fields, files) => 
    if (err) 
      next(err);
      return;
    
    res.json( fields, files );
  );
);

https://www.npmjs.com/package/formidable

【讨论】:

【参考方案12】:

express-fileupload 看起来是目前唯一仍在使用的中间件。

在同一个示例中,multerconnect-multiparty 给出了未定义的 req.filereq.files 值,但 express-fileupload 有效。 p>

还有很多关于req.file/req.files的空值的疑问和问题。

【讨论】:

以上是关于使用 Express 4.0 上传文件:req.files undefined的主要内容,如果未能解决你的问题,请参考以下文章

使用 express 上传文件

使用express的bodyParser上传文件,请问如何设置文件大小

在 Express 路由器中使用 multer 进行文件上传

如何使用 nodejs / express 上传和读取文件

在 ASP.NET 4.0 环境下使用 c# 进行多文件上传

使用 Multer 重命名上传的文件不起作用 (Express.js)