iT邦幫忙

1

[Node.js]實作multer檔案上傳(二)

本系列目標

ps(本系列文章將引用ToDo List的專案去演示,抱歉稍後補上專案GitHub連結)

這篇文章你將學習到

  • 將圖片存放在storage資料夾中,並將圖片渲染在EJS上面

開始實作

概念

利用multer將圖片存在後端storage,取得圖片儲存的相對路徑,最後EJS在 img tag的src路徑去引入該圖片
優點:

  • 可以讓client端異步的方式去request檔案,分散一次接收並阻塞式的解析大量資料
  • 後端方便集中管理、修改圖片

設定存放圖片

dest/storage指定圖片存入的位置

multer(opt)這個方法的opt接受指定的key value pair物件,其中兩個我們會用來指定圖片存放位置的就是dest和storage這兩個。

dest

dest就是destination(目的地)的簡稱,它的值要是string來指定存放路徑,在之前我已經用express.static(__dirname + '/public')去告訴express我靜態檔案是放在public資料夾下面,__dirname就是我的env記錄著我專案根目錄的位置,這樣前後組合起來就是一個絕對路徑。

var upload = multer({dest: "public/images/uploads"})

storage

storage有分存MemoryStorage或DiskStorage

  • MemoryStorage: 簡單且沒有任何選項,會將檔案以buffer object的形式存進記憶體中,object的key叫做buffer(注意!這動作可能會耗盡你的記憶體,請斟酌檔案的總容量)
var storage = multer.memoryStorage()
var upload = multer({ storage: storage })
  • DiskStorage: 有2個客製化的儲存選項
  • destination
  • filename
    下面這個例子我們控制了destination(檔案存放的位置),若成功則執行cb(客製化的成功訊息, 存放的相對位置)。filename(編輯檔名),若成功則執行cb(客製化的成功訊息, 客製化檔案名稱),ps.這裡的file是multer以物件的型別存放檔案資訊的地方。
 const storage = multer.diskStorage({
     destination: function (req, file, cb) {
       cb(null, 'public')
     },
     filename: function (req, file, cb) {
       cb(null, file.filename: + '-' + Date.now())
     }
 })
 const upload = multer({storage: storage})

接下來,我們要修改成能在後端預覽圖片

一般來說,把圖片存在storage後,是無法直接用預覽器去預覽圖片,這樣對於管理不是很友善,所以我們可以引用Node原生的方式fs.rename()來讓storage中的圖片可以被預覽。

引入fs()

routes/index.js加入

const fs = require('fs')

在上傳圖片router.post()裡面加入

這裡我們透過fs.rename()的方式修改了圖片存放的路徑,以及成功則執行callback回傳成功訊息。
表達式: fs.rename(oldPath, newPath, callback)
第一個參數oldname即是該圖的原路徑,第二個newPath則是新路徑,我們將它指定在一個變數中方便查看,第三個參數即是執行後的callback成功訊息。

let newPath = `public/images/uploads/${req.file.originalname}`
fs.rename(req.file.path, newPath, () => {
    res.json({result: 'image uploaded successful'})
})

上傳成功,我們檢查一下圖片在不在

成功,而且可以直接預覽圖片

https://ithelp.ithome.com.tw/upload/images/20200518/20121402cF3VWCh4Ng.png

我們把圖片相對位置imgPath存入DB

在router.post加入imgPath

var imgPath = {image: `/images/uploads/${req.file.originalname}`}
MongoClient.connect(url, function(err, db) {
    if (err) throw err;
    var dbo = db.db("todolist");
    dbo.collection("images").insertOne(imgPath, function(err, res) {
          if (err) throw err;
          console.log("1 image inserted");
          db.close();
    });
});

看一下Mongo DB是否有寫入成功

現在我們已經可以把圖片存放好,並且DB也將圖片的相對位置記錄和規劃,DB只負責記錄網址就可以了。減輕不少DB的負擔。
https://ithelp.ithome.com.tw/upload/images/20200518/20121402Vrz22N8xqU.png

在EJS渲染這張圖片

在views/index.ejs修改img tag

 <img src="<%= doc.image %>"/>

完成

我們打開網址http://localhost:3000/

https://ithelp.ithome.com.tw/upload/images/20200518/20121402TsovdmeZvR.png

今日感想

終於可以理解為什麼要把圖片存在storage的好處,實作下來我發現,其實不一定要把圖片存放在本機中,也可以用託管的方式把圖片存在第三方的空間,例如AWS有個S3的圖片儲存空間。

下一篇,我們把圖片託管在第三方空間。


尚未有邦友留言

立即登入留言