返回
Featured image of post Multer - 圖片上傳

Multer - 圖片上傳

處理 multipart/form-data 的 node.js 中間件,用於上傳文件

前言:

圖片上傳算是一個蠻常見的功能,基本上是一個網站,不管是後台還是前台基本上是都會有這項功能的。
這篇文章主要講解後端圖片處理的部分。
之後會介紹前端圖片裁切套件。

安裝

npm i multer

官網範例

const express = require('express')
const multer  = require('multer')
const upload = multer({ dest: 'uploads/' })

const app = express()

app.post('/profile', upload.single('avatar'), function (req, res, next) {
  // 單筆
  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any
})

app.post('/photos/upload', upload.array('photos', 12), function (req, res, next) {
  // 多筆
  // req.files is array of `photos` files
  // req.body will contain the text fields, if there were any
})

const cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 8 }])
app.post('/cool-profile', cpUpload, function (req, res, next) {
  // middleware的方式
  // req.files is an object (String -> Array) where fieldname is the key, and the value is array of files
  //
  // e.g.
  //  req.files['avatar'][0] -> File
  //  req.files['gallery'] -> Array
  //
  // req.body will contain the text fields, if there were any
})

注意事項

  1. Multer 的 前端 Request 只能用 form-data 的方式推送 header 記得塞入 multipart/form-data
  2. Express 記得啟用 form-data 的方式 記得 app.use('body-parser') // body-parser 是 Express 解析 request 的套件
  3. 如果上傳大小相對大的文件使用 multer.memoryStorage() 注意會導致 Memory 不足
  4. 若是 使用 multer.memoryStorage() Multer 推送 Buffer 結束 Request 會將 Memory 釋放

multer with gcs - by TS

使用 Multer 上傳至 GCS,簡單來說也是透過 multer 再處理 Buffer 至 GCS

// 封裝的 GCS Package TS
imort { Storage, Bucket } from '@google-cloud/storage';

export type GcsFileUploadResult = {
    message?: string         // 訊息
    filename?: Array<string> // 檔案名稱
}; 

export class GCS { 
    private storage: Storage
    private bucket: Bucket
    constructor(bucket) {
        this.storage = new Storage({ keyFilename: process.env.GCP_AUTH_LOCATION }) // GCP_AUTH_LOCATION - GCP AUTH JSON key
        this.bucket = storage.bucket(process.env.GCS_BUCKETNAME) // GCS_BUCKETNAME - GCS Bucket Name
    }
    /**
     * 上傳
     * @param {Express.Multer.File} file 檔案
     * @param {string} name 檔名 ex: xxx.jpg
     * @param {Promise<GcsFileUploadResult>}
     */
    private upload(file: Express.Multer.File, name: string): Promise<GcsFileUploadResult> {
        return new Promise((resolve, reject) => {
          const blob = this.bucket.file(name);
          const blobStream = blob.createWriteStream();
          blobStream
          .on('finish', () => resolve({ message: '上傳成功', filename: [name] }));
          .on('error', () => reject({ message: '上傳失敗', filename: [name] }));
          blobStream.end(file.buffer);
        })
    }
    /**
     * 上傳至GCS
     * @param {Express.Multer.File} file 檔案
     * @param {string} name 檔名 ex: xxx.jpg
     * @param {Promise<GcsFileUploadResult>}
     */
    uploadToGCS(file: Express.Multer.File, name: string): Promise<GcsFileUploadResult> {
        let result: GcsFileUploadResult;
        try { result = await this.upload(file, name) };
        catch (err) { result.message = '檔案上傳失敗' };
        return result;
    }
}
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus