无法使用app.use(multer)。出现“需要中间件函数”错误。

43

我刚开始学习 NodeJS,现在遇到了一个问题。我想上传文件到我的服务器上。为了这样做,我搜索并找到了这个模块multer。按照 GitHub 上的示例操作可以实现:

var express = require('express');
var multer = require('multer');
var upload = multer({ dest: 'uploads/' });

var app = express()

app.post('/uploadImage', upload.single('image'), function(req, res) {
    console.log(req.file);
});

使用FormData将图像上传到/uploadImage后,该图像将保存在uploads/目录中。问题在于图像以奇怪的名称保存,我想用原始名称保存它。 为了这样做,我了解到我需要调用app.use(multer({dest:'uploads/'}))',然后我就可以在我的函数中访问req.file

app.post('/uploadImage', function(req, res) {
    console.log(req.file);
});

但是在尝试使用app.use()时我收到了一个错误:

TypeError: app.use() requires middleware functions
    at EventEmitter.use (project\node_modules\express\lib\application
.js:209:11)

我正在使用 NodeJS 0.12.7 和 Express 4.13.1

如何实现上传?谢谢。


1
https://dev59.com/U1wZ5IYBdhLWcg3waPrX#31495796 - stdob--
哦我的天啊... 我发誓我在这里搜索过了... 谢谢stdob... 但是奇怪的是(对我来说),它仍然会自动上传文件... 我以为我能控制并使用 fs 写入它... 我会想办法的,谢谢。 - João Menighin
7个回答

62

您需要在以下表单中使用app.use(multer({dest:'./uploads/'})):

app.use(multer({dest:'./uploads/'}).single(...));
app.use(multer({dest:'./uploads/'}).array(...));
app.use(multer({dest:'./uploads/'}).fields(...));

ie:

app.use(multer({dest:'./uploads/'}).single('photo'));

请确保有以下类似内容:

<form action="/postPhotos" enctype="multipart/form-data" method="post">
    <input type="file" name="photo">
    <input type="submit" value="Upload photo">
</form>

在你的HTML中。


23
var app = require('express');

var multer = require('multer');

app=express();

app.use(multer({dest:__dirname+'/file/uploads/'}).any());

app.post('/upload',function(req,res){

    console.log(req.files);

    res.redirect('/');

});

5
如果这篇回答解释一下如何回答问题并解决问题,那么它会更好。 - William Price
StackOverflow要求您仅使用英语发布问题、评论和答案。请使用[编辑]链接直接更新您的答案。 - William Price

12

@127.0.0.1的回答是正确的,但是如果你正在使用Express Router,代码会有一点变化:

答案来自 @127.0.0.1,但如果您使用的是 Express Router ,则代码会略有变化:

var express = require('express');
var multer = require('multer');

var router = express.Router();

var uploads = multer({
  dest: 'public/uploads/'
});

router.post('/upload', uploads.single('avatar'), function(req, res, next) {
  console.log(req.file);

  //...
});

而最重要的是,表单编码应该像已经说过的那样是enctype="multipart/form-data",就像这样:

<form action="/upload" enctype="multipart/form-data" method="post">
    <input type="file" name="avatar">
    <input type="submit" value="Go avatar go!">
</form>

嗨,我正在使用 multer, expres, ng2-file-upload 堆栈,并且您的代码对我来说并不起作用。req.file 未定义,我的文件信息在 req.files 上(在我的 HTML 中,我没有多个选择器)。当我点击上传按钮时,服务器返回已上传的文件,但是该文件不存在于服务器上。我做错了什么? - Hanzo
我建议先不使用Angular进行测试。我的意思是使用Postman、CURL或您喜欢的工具直接向后端发送请求。如果这样可以正常工作,那么问题就在前端。如果不能正常工作,那么问题就在后端。这并不能解决问题,但它会帮助您更快地解决问题。 - Salvatorelab
如果我添加这个app.use(multer({storage:storage}).single('file'));,它可以正常工作,但是带回调函数时不符合预期。你能看一下这个问题吗?https://stackoverflow.com/questions/44165037/files-not-uploading-with-ng2-file-upload - Hanzo
1
Salvatorelab,我已经搜索了2个多小时,试图弄清楚为什么在使用Express路由器时无法调试“upload.single”不是一个函数。只是想指出这一点,因为这不是OP试图解决的问题,但可能会帮助其他人。 - Paul W

7

使用multer无法更改文件名,但是可以使用Node.js的stream和fs模块将已上传文件的内容复制到同一文件夹中的新文件(设置为原始文件名),并删除旧文件。

首先,在您的Node脚本中导入fs、path和multer。

var express = require('express');
var multer = require('multer');
var fs = require('fs');
var pathModule = require('path');

现在,使用multer设置任何类型文件的目标目录如下:
var app = express();
app.use(multer({dest:__dirname+'/resoucres/'}).any());

现在可以使用stream和fs来解决你的问题。
app.post('/uploadImage', function(request, response) {
    var readerStream = fs.createReadStream(request.files[0].path);
    var dest_file = pathModule.join(request.files[0].destination, request.files[0].originalname);
    var writerStream = fs.createWriteStream(dest_file);

    var stream = readerStream.pipe(writerStream);
    stream.on('finish', function(){
        fs.unlink(request.files[0].path);
    });
});

6

自1.0.0版本以来

var upload = multer({ dest: 'tmp/' });
app.post('/file_upload', upload.single('photo'), function (req, res) {

2
这里的 upload.single('photo') 是什么意思? - Ashh

4

在app.js中改用app.use(multer({dest:'./uploads/'}).single('photo'));对于我来说可以启动服务器


1
你能再解释一下吗? - Dieter Meemken

2

我遇到了同样的问题。但我解决了它。 对于第一个问题,如何获取原始文件名? 我打印了整个请求,发现我们可以通过路径 "req.file.originalname" 来获取原始名称。

至于另一个问题,如何使用 "app.use()"?
请参考:这里


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接