multer模組diskstorage方式注意事項
阿新 • • 發佈:2019-02-06
------------------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(
...