如何在Express中管理存儲和處理通過表單上傳的文件
這是一個允許用戶上傳文件的HTML表單的示例:
<form method="POST" action="/submit-form" enctype="multipart/form-data">
<input type="file" name="document" />
<input type="submit" />
</form>
不要忘記在表單中添加
enctype="multipart/form-data"
,否則文件將無法被上傳
當用戶點擊提交按鈕時,瀏覽器會自動向與該頁面相同源頭的/submit-form
URL 發送一個POST
請求。瀏覽器將數據以multipart/form-data
的形式而不是編碼的形式(即普通表單的application/x-www-form-urlencoded
)發送出去。
在服務器端,處理multipart數據可能會很棘手且容易出錯,因此我們將使用一個名為formidable的實用庫。這是GitHub倉庫,它擁有超過4000顆星且得到良好的維護。
您可以使用以下命令來安裝它:
npm install formidable
然後在您的Node.js文件中引入它:
const express = require('express')
const app = express()
const formidable = require('formidable')
現在,在/submit-form
路由的POST
端點中,我們使用formidable.IncomingForm()
實例化一個新的Formidable表單:
app.post('/submit-form', (req, res) => {
new formidable.IncomingForm()
})
在這樣做之後,我們需要能夠解析表單。我們可以通過提供一個回調函數來同步進行解析,這意味著所有文件都被處理,一旦formidable完成它們的處理,它就會使它們可用:
app.post('/submit-form', (req, res) => {
new formidable.IncomingForm().parse(req, (err, fields, files) => {
if (err) {
console.error('Error', err)
throw err
}
console.log('Fields', fields)
console.log('Files', files)
for (const file of Object.entries(files)) {
console.log(file)
}
})
})
或者,您可以使用事件而不是回調函數。例如,當每個文件被解析時,或者其他事件(如文件處理完成、接收到非文件字段、或者出現錯誤)發生時,您可以收到通知:
app.post('/submit-form', (req, res) => {
new formidable.IncomingForm().parse(req)
.on('field', (name, field) => {
console.log('Field', name, field)
})
.on('file', (name, file) => {
console.log('Uploaded file', name, file)
})
.on('aborted', () => {
console.error('Request aborted by the user')
})
.on('error', (err) => {
console.error('Error', err)
throw err
})
.on('end', () => {
res.end()
})
})
無論您選擇哪種方式,您將獲得一個或多個Formidable.File對象,這些對象提供有關上傳的文件的信息。這是一些您可以調用的方法:
file.size
,文件大小(以字節為單位)file.path
,文件寫入的路徑file.name
,文件的名稱file.type
,文件的MIME類型
路徑默認為臨時文件夾,如果您侦聽fileBegin
事件,可以修改它:
app.post('/submit-form', (req, res) => {
new formidable.IncomingForm().parse(req)
.on('fileBegin', (name, file) => {
file.path = __dirname + '/uploads/' + file.name
})
.on('file', (name, file) => {
console.log('Uploaded file', name, file)
})
//...
})