------------------8.15更新------------------
关于req.body为空的问题,之前在multer的github上开了个issue提了这个问题,multer的作者回复我说目前没有直接的solution,但推荐一个workaround:
...
formData.append('uid',uid);
formData.append('avatar',avatarFile);
在前端js控制数据装载的顺序,只要保证数据装载在file文件之前即可,亲测有效。
-----------------------------------------
以前用的时候都没留意。。。
multer 虽然给出了一个自定义存储的方式,让开发者设定存储路径和命名:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now())
}
})
var upload = multer({ storage: storage })
这里有两点值得留意:
1是destination和filename函数的参数req,在这里req.body是空对象{},未装载formdata的文本域数据。
//想直接根据req.body的参数动态创建文件夹存储文件是不行的!!
destination: function (req, file, cb) {
console.log('this is file')
console.log(file)
let avatarPath = path.join(__dirname,`../../asserts/${req.body.uid}/avatar`);
if (!fs.existsSync(avatarPath)) {
fs.mkdirSync(avatarPath);
}
cb(null, avatarPath)
},
...
类似上面直接根据req.body.xxx动态创建文件夹就不行了。
2是file虽然装载了文件对象,但是信息不全,下面两张图分别是multer.diskstorage回调和后续中间件函数中file的信息:
当我们想根据请求中的数据动态创建文件夹保存文件的时候,由于diskstorage方式必须先确定保存路径、req.body中未存储任何信息、且其file参数只装载极有限的信息,显然是不行的。
multer插件提供了另一种方式MemoryStorage,在upload.single('avatar')之后将文件转为buffer保存在req.file.buffer中,这时候我们就可以在获取req.body.xxx后,通过fs创建文件夹,并通过fs.writeFile(path,new Buffer(req.file.buffer),callback)的方式实现了。
//Demo
var storageAvatar = multer.memoryStorage()
var uploadAvatar = multer({ storage: storageAvatar })
exports.avatarMiddleWare= uploadAvatar.single('avatar');
exports.avatar=function(req,res){
let uid = req.body.uid,filetype;
let mime = req.file.mimetype.split('/');
if(mime[0] === 'image') filetype = `.${mime[1]}`;
...
fs.writeFile(path.join(__dirname,`../../asserts/userData/${uid}/avatar/avatar-${t imeStamp}${filetype}`),
new Buffer(req.file.buffer),
function(err) {
if(err) {console.log(err)}
});
UserModel.findOneAndUpdate(
...