1. 程式人生 > >multer模組diskstorage方式注意事項

multer模組diskstorage方式注意事項

------------------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(
  ...