/

在Express中處理表單上傳的文件

在Express中處理表單上傳的文件

如何在Express中管理存儲和處理通過表單上傳的文件

這是一個允許用戶上傳文件的HTML表單的示例:

1
2
3
4
<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顆星且得到良好的維護。

您可以使用以下命令來安裝它:

1
npm install formidable

然後在您的Node.js文件中引入它:

1
2
3
const express = require('express')
const app = express()
const formidable = require('formidable')

現在,在/submit-form路由的POST端點中,我們使用formidable.IncomingForm()實例化一個新的Formidable表單:

1
2
3
app.post('/submit-form', (req, res) => {
new formidable.IncomingForm()
})

在這樣做之後,我們需要能夠解析表單。我們可以通過提供一個回調函數來同步進行解析,這意味著所有文件都被處理,一旦formidable完成它們的處理,它就會使它們可用:

1
2
3
4
5
6
7
8
9
10
11
12
13
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)
}
})
})

或者,您可以使用事件而不是回調函數。例如,當每個文件被解析時,或者其他事件(如文件處理完成、接收到非文件字段、或者出現錯誤)發生時,您可以收到通知:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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事件,可以修改它:

1
2
3
4
5
6
7
8
9
10
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)
})
//...
})

tags: [“Express”, “file uploads”, “forms”, “multipart/form-data”]