iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0

在前面的課程中,我們已經學會了如何接收前端傳來的 JSON 資料 (透過 req.body)。但是,當前端需要上傳「檔案 (圖片、影片、PDF)」時,傳輸格式會變成 multipart/form-data,這時 Express 內建的 express.json() 就完全看不懂了。

為了解決這個問題,Node.js 生態系中最受歡迎的檔案上傳處理套件 Multer 就此誕生。它也是一個「中介軟體 (Middleware)」,專門用來攔截並解析上傳的檔案。

1. 安裝 Multer 與準備資料夾

首先,在專案中安裝 Multer:

npm install multer

接著,在你的專案根目錄下,手動建立一個名為 uploads 的資料夾。這將是我們用來存放使用者上傳檔案的地方。

2. 實作:建立上傳中介軟體

在 middlewares 資料夾下,新增一個 upload.js:

import multer from 'multer';
import path from 'path';

// 1. 設定儲存引擎 (Storage Engine)
const storage = multer.diskStorage({
    // 設定檔案儲存的目的地
    destination: (req, file, cb) => {
        cb(null, 'uploads/'); // 存入我們剛剛建立的 uploads 資料夾
    },
    // 設定檔案名稱 (避免檔名重複導致覆蓋)
    filename: (req, file, cb) => {
        // 取得原始副檔名 (例如 .jpg, .png)
        const ext = path.extname(file.originalname);
        // 組合新檔名:欄位名稱 + 加上目前時間戳記 + 副檔名
        const uniqueName = `${file.fieldname}-${Date.now()}${ext}`;
        cb(null, uniqueName);
    }
});

// 2. 設定檔案過濾器 (安全防禦:只允許圖片)
const fileFilter = (req, file, cb) => {
    // 檢查 mimetype 是否為圖片
    if (file.mimetype.startsWith('image/')) {
        cb(null, true); // 接受檔案
    } else {
        cb(new Error('檔案格式錯誤,只能上傳圖片檔案!'), false); // 拒絕檔案
    }
};

// 3. 匯出設定好的 multer 實例
export const upload = multer({ 
    storage: storage,
    fileFilter: fileFilter,
    limits: {
        fileSize: 2 * 1024 * 1024 // 限制檔案大小為 2MB
    }
});

3. 在路由中使用 Multer

現在我們要把寫好的上傳守衛,套用到具體的 API 路由上。打開你的 routes/users.js (或是新開一個測試路由檔案):

import express from 'express';
import { upload } from '../middlewares/upload.js'; // 引入剛剛寫好的 Multer 中介軟體

const router = express.Router();

// 使用 upload.single('avatar') 攔截單一檔案
// 'avatar' 必須和前端表單 (<input type="file" name="avatar">) 的 name 屬性完全一致!
router.post('/upload-avatar', upload.single('avatar'), (req, res) => {
    try {
        // 如果沒有上傳檔案,req.file 會是 undefined
        if (!req.file) {
            return res.status(400).json({ message: '請選擇要上傳的圖片' });
        }

        // req.file 包含了檔案的詳細資訊
        console.log("上傳成功!檔案資訊:", req.file);

        res.status(200).json({ 
            message: '大頭貼上傳成功!',
            // 回傳檔案的路徑給前端,讓前端可以顯示圖片
            imageUrl: `/${req.file.path}` 
        });

    } catch (error) {
        res.status(500).json({ message: '上傳失敗', error: error.message });
    }
});

export default router;

4. 靜態檔案託管 (Static Files)

你可能會問:「檔案存進 uploads 資料夾了,那前端要怎麼透過網址看到這張圖片?」
Express 預設是會阻擋任何人存取伺服器上的實體檔案的。為了讓 uploads 資料夾公開,你需要回到 app.js,加入這一行「靜態檔案託管」的設定:

// 告訴 Express:把 'uploads' 資料夾變成公開的靜態資源目錄
app.use('/uploads', express.static('uploads'));

現在,如果你的 API 回傳圖片路徑是 /uploads/avatar-1700000.jpg,前端只要訪問 http://localhost:3000/uploads/avatar-1700000.jpg,就能順利看到剛剛上傳的圖片了!


上一篇
Day 23:中介軟體 (Middleware) 實戰與錯誤處理機制
系列文
不要再說你不會後端!30 天 Node.js 降維打擊指南 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言