我正在尝试获得一个与 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');
});
.. 以及随附的哈巴狗代码:
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');
});
});
});
body-parser
模块仅处理 JSON 和 urlencoded 表单提交,而不处理多部分(如果您上传文件,则会出现这种情况)。
connect-busboy
或 multer
或 connect-multiparty
的东西(多方/强大是最初在 Express bodyParser 中间件中使用的)。另外,FWIW,我正在 Busboy 之上开发一个更高级别的层,称为 reformed
。它带有 Express 中间件,也可以单独使用。
这是我通过谷歌搜索发现的:
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");
});
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!!!');
});
看起来
body-parser
did 支持在 Express 3 中上传文件,但是当 Express 4 不再包含 Connect 作为依赖项时,它的支持就被放弃了
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' } }
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
});
希望这有帮助!
只是为了添加到上面的答案,您可以将
express-fileupload
的使用简化为仅需要它的单个路线,而不是将其添加到每个路线中。
let fileupload = require("express-fileupload");
...
//Make sure to call fileUpload to get the true handler
app.post("/upload", fileupload(), function(req, res){
...
});
请使用以下代码
var fileupload = require("express-fileupload");
app.use(fileUpload());
此功能需要安装包,有很多,但我个人更喜欢“express-fileupload”。只需在终端中通过“npm i express-fileupload”命令安装它,然后在根文件中使用它
const fileUpload = require("express-fileupload");
app.use(fileUpload());
我在 methodOverride 中间件之前添加了 multer 作为全局中间件, 它在 router.put 中也有效。
const upload = multer({
storage: storage
}).single('featuredImage');
app.use(upload);
app.use(methodOverride(function (req, res) {
...
}));
const fileUpload = require("express-fileupload");
router.route("/uploads").post(fileUpload(), uploadProductImage);
//在路由中添加 fileUpload() 中间件对我有用。
问题解决了!!!!!!!
结果
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');
强大:
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 });
});
});
express-fileupload
看起来是目前唯一仍然有效的中间件。
在同一示例中,
multer
和connect-multiparty
给出未定义的值req.file或req.files,但express-fileupload
有效。
并且对于 req.file/req.files 的空值提出了很多疑问和问题。