Multer 是一個用於處理 multipart/form-data
的 node.js 中介軟體,主要用於上傳檔案。它建立於 busboy 之上,以達到最大的效率。
注意:Multer 不會處理任何非 multipart(multipart/form-data
)的表單。
此 README 也提供其他語言版本
$ npm install --save multer
Multer 會將 body
物件和 file
或 files
物件新增到 request
物件。body
物件包含表單文字欄位的數值,file
或 files
物件包含透過表單上傳的檔案。
基本用法範例
別忘了在表單中加入 enctype="multipart/form-data"
。
<form action="/profile" method="post" enctype="multipart/form-data">
<input type="file" name="avatar" />
</form>
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) {
// 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
})
如果您需要處理純文字 multipart 表單,您應該使用 .none()
方法
const express = require('express')
const app = express()
const multer = require('multer')
const upload = multer()
app.post('/profile', upload.none(), function (req, res, next) {
// req.body contains the text fields
})
以下是 multer 用於 HTML 表單的範例。特別注意 enctype="multipart/form-data"
和 name="uploaded_file"
欄位
<form action="/stats" enctype="multipart/form-data" method="post">
<div class="form-group">
<input type="file" class="form-control-file" name="uploaded_file">
<input type="text" class="form-control" placeholder="Number of speakers" name="nspeakers">
<input type="submit" value="Get me the stats!" class="btn btn-default">
</div>
</form>
然後在你的 javascript 檔案中,你會加入這些行來存取檔案和主體。在你的上傳函式中使用表單中的 name
欄位值非常重要。這會告訴 multer 它應該在請求中的哪個欄位尋找檔案。如果這些欄位在 HTML 表單和你的伺服器上不同,你的上傳會失敗
const multer = require('multer')
const upload = multer({ dest: './public/data/uploads/' })
app.post('/stats', upload.single('uploaded_file'), function (req, res) {
// req.file is the name of your file in the form above, here 'uploaded_file'
// req.body will hold the text fields, if there were any
console.log(req.file, req.body)
});
每個檔案包含下列資訊
金鑰 | 說明 | 備註 |
---|---|---|
fieldname |
表單中指定的欄位名稱 | |
originalname |
使用者電腦上的檔案名稱 | |
encoding |
檔案的編碼類型 | |
mimetype |
檔案的 Mime 類型 | |
size |
檔案大小(以位元組為單位) | |
destination |
檔案已儲存的資料夾 | DiskStorage |
filename |
destination 中的檔案名稱 |
DiskStorage |
path |
上傳檔案的完整路徑 | DiskStorage |
buffer |
整個檔案的 Buffer |
MemoryStorage |
multer(opts)
Multer 接受一個選項物件,其中最基本的是 dest
屬性,它告訴 Multer 在哪裡上傳檔案。如果你省略選項物件,檔案將會保留在記憶體中,而不會寫入磁碟。
預設情況下,Multer 會重新命名檔案,以避免命名衝突。重新命名函式可以根據你的需求進行自訂。
以下是可以傳遞給 Multer 的選項。
金鑰 | 說明 |
---|---|
dest 或 storage |
檔案儲存位置 |
fileFilter |
控制哪些檔案可以接受的函式 |
limits |
上傳資料的限制 |
preservePath |
保留檔案的完整路徑,而不要只保留基本名稱 |
在一般的網路應用程式中,可能只需要 dest
,並按照以下範例進行設定。
const upload = multer({ dest: 'uploads/' })
如果您想要對上傳有更多控制權,您會想要使用 storage
選項,而不是 dest
。Multer 隨附儲存引擎 DiskStorage
和 MemoryStorage
;第三方提供更多引擎。
.single(fieldname)
接受一個名稱為 fieldname
的單一檔案。單一檔案將儲存在 req.file
中。
.array(fieldname[, maxCount])
接受一個檔案陣列,所有檔案的名稱都為 fieldname
。如果上傳的檔案超過 maxCount
,則選擇性地報錯。檔案陣列將儲存在 req.files
中。
.fields(fields)
接受由 fields
指定的混合檔案。一個包含檔案陣列的物件將儲存在 req.files
中。
fields
應為一個物件陣列,其中包含 name
和選擇性的 maxCount
。範例
[
{ name: 'avatar', maxCount: 1 },
{ name: 'gallery', maxCount: 8 }
]
.none()
僅接受文字欄位。如果進行任何檔案上傳,將發出代碼為「LIMIT_UNEXPECTED_FILE」的錯誤。
.any()
接受透過網路傳輸的所有檔案。一個檔案陣列將儲存在 req.files
中。
警告:請務必始終處理使用者上傳的檔案。切勿將 multer 新增為全域中介軟體,因為惡意使用者可能會將檔案上傳到您未預期的路由。僅在您處理上傳檔案的路由上使用此函式。
storage
DiskStorage
磁碟儲存引擎讓您完全控制將檔案儲存在磁碟中的方式。
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '/tmp/my-uploads')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix)
}
})
const upload = multer({ storage: storage })
有兩個可用的選項,destination
和 filename
。它們都是用來決定檔案應儲存在何處的函式。
destination
用來決定上傳的檔案應儲存在哪個資料夾中。這也可以作為一個 字串
提供(例如 '/tmp/uploads'
)。如果沒有提供 destination
,則使用作業系統的臨時檔案預設目錄。
注意:當提供 destination
作為函數時,您有責任建立目錄。當傳遞字串時,multer 會確保為您建立目錄。
filename
用於決定檔案在資料夾內的名稱。如果沒有提供 filename
,每個檔案都會獲得不包含任何副檔名的隨機名稱。
注意:Multer 不会為您附加任何副檔名,您的函數應傳回一個包含副檔名的完整檔名。
每個函數都會傳遞要求 (req
) 和一些關於檔案的資訊 (file
) 以協助決策。
請注意,req.body
可能尚未完全填入。這取決於用戶端傳輸欄位和檔案到伺服器的順序。
若要了解在回呼中使用的呼叫慣例(需要將 null 傳遞為第一個參數),請參閱 Node.js 錯誤處理
MemoryStorage
記憶體儲存引擎將檔案儲存在記憶體中,作為 Buffer
物件。它沒有任何選項。
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
使用記憶體儲存時,檔案資訊將包含一個稱為 buffer
的欄位,其中包含整個檔案。
警告:當使用記憶體儲存時,上傳非常大的檔案或大量相對較小的檔案可能會導致您的應用程式用盡記憶體。
limits
一個指定下列選用屬性的尺寸限制的物件。Multer 將此物件直接傳遞給 busboy,而屬性的詳細資訊可以在 busboy 的頁面 中找到。
以下整數值可用
金鑰 | 說明 | 預設值 |
---|---|---|
fieldNameSize |
最大欄位名稱大小 | 100 位元組 |
fieldSize |
最大欄位值大小(以位元組為單位) | 1MB |
fields |
非檔案欄位的最大數量 | 無限 |
fileSize |
對於多部分表單,最大檔案大小(以位元組為單位) | 無限 |
files |
對於多部分表單,檔案欄位的最大數量 | 無限 |
parts |
對於多部分表單,要分析的標頭 key=>value 對的最大數量 | 無限 |
headerPairs |
對於多部分表單,要分析的標頭 key=>value 對的最大數量 | 2000 |
指定限制值可以幫助保護您的網站免於遭受拒絕服務 (DoS) 攻擊。
fileFilter
將此設定為一個函式,以控制應該上傳哪些檔案,以及應該略過哪些檔案。該函式應如下所示
function fileFilter (req, file, cb) {
// The function should call `cb` with a boolean
// to indicate if the file should be accepted
// To reject this file pass `false`, like so:
cb(null, false)
// To accept the file pass `true`, like so:
cb(null, true)
// You can always pass an error if something goes wrong:
cb(new Error('I don\'t have a clue!'))
}
遇到錯誤時,Multer 會將錯誤委派給 Express。您可以使用 標準 Express 方式 顯示一個友善的錯誤頁面。
如果您想特別從 Multer 擷取錯誤,您可以自行呼叫中介軟體函式。此外,如果您只想擷取 Multer 錯誤,您可以使用附加到 multer
物件本身的 MulterError
類別(例如,err instanceof multer.MulterError
)。
const multer = require('multer')
const upload = multer().single('avatar')
app.post('/profile', function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
} else if (err) {
// An unknown error occurred when uploading.
}
// Everything went fine.
})
})
有關如何建立您自己的儲存引擎的資訊,請參閱 Multer 儲存引擎。