怎么處理文件上傳?下面本篇文章給大家介紹一下node項(xiàng)目中如何使用express來(lái)處理文件的上傳,希望對(duì)大家有所幫助!
上傳單個(gè)文件
我們可以使用 express 官方出品的第三方中間件 multer 來(lái)處理,先是安裝:
npm i multer
然后我先放段比較完整的代碼,之后解釋:
const express = require('express') const multer = require('multer') const app = express() const upload = multer({ dest: './uploads' }) app.post('/upload', upload.single('file'), (req, res) => { console.log(req.file) res.end('上傳成功') }) app.listen(4396, () => { console.log('服務(wù)器開啟') })
引入后的 multer
為一個(gè)函數(shù),執(zhí)行它得到 upload
對(duì)象,執(zhí)行時(shí)可以傳入配置,比如設(shè)置 dest
(destination 的縮寫) 為 './uploads'
,用于指定上傳后的文件的存放位置:
const upload = multer({ dest: './uploads' })
由于對(duì)上傳文件的處理并不是普遍需要的,所以對(duì) upload
的使用是直接在匹配上傳路徑(我們定義為 '/upload'
)和方法(一般為 POST)的 app.post('/upload', )
內(nèi),處理的是單個(gè)文件上傳,所以使用 upload.single()
方法,傳入的 'file'
(自定義,也可以為其它名字) 為上傳文件時(shí)的 key:
其執(zhí)行會(huì)返回一個(gè)中間件函數(shù),將得到的文件的數(shù)據(jù)賦值到 req.file
,而文本字段的信息則會(huì)放在 req.body
中,并調(diào)用 next()
,這樣我們就可以接著注冊(cè)一個(gè)中間件,打印查看文件信息,并向客戶端返回請(qǐng)求結(jié)果 :
app.post('/upload', upload.single('file'), (req, res) => { console.log(req.body) console.log(req.file) res.end('上傳成功') })
發(fā)起上傳請(qǐng)求后,打印得到的 req.body
如下:
[Object: null prototype] { name: 'jay' }
注意,如果請(qǐng)求的 body 使用 form-data
格式攜帶的數(shù)據(jù)里沒(méi)有文件,而僅僅是一些文本字段,則 upload.single('file')
可以換成 upload.any()
。
打印得到的 req.file
如下:
{ fieldname: 'file', originalname: '1.png', encoding: '7bit', mimetype: 'image/png', destination: './uploads', filename: '4c5781db70269d90cc57249e95a28894', path: 'uploads\\4c5781db70269d90cc57249e95a28894', size: 904454 }
并且文件會(huì)存儲(chǔ)在 uploads 目錄下:
可以看到,文件名為哈希值,且沒(méi)有后綴,在 vscode 里無(wú)法直接查看圖片:
但圖片文件是可用的,使用 ps 是可以直接打開查看的。那如果想讓文件存儲(chǔ)時(shí)的文件名是添加后綴的,要怎么辦呢?解決方案是在執(zhí)行 const upload = multer()
時(shí),傳入的配置對(duì)象不再設(shè)置 dest
的值而改為設(shè)置 storage
:
const storage = multer.diskStorage({ destination(req, file, cb) { cb(null, './uploads') }, filename(req, file, cb) { cb(null, Date.now() + '-' + file.originalname) } }) const upload = multer({ storage })
storage
對(duì)象由 multer.diskStorage()
生成,其內(nèi)部傳入對(duì)象,該對(duì)象有兩個(gè)方法屬性,它們都有 3 個(gè)參數(shù),請(qǐng)求對(duì)象 req
,文件信息 file
,和一個(gè)回調(diào)函數(shù) cb
:
destination
就是配置文件存儲(chǔ)路徑的,其作用等同于之前直接往multer()
傳入的{ dest: './uploads' }
,存儲(chǔ)路徑通過(guò) cb 的第二個(gè)參數(shù)傳入,cb 的第一個(gè)參數(shù)可以傳 Error 對(duì)象或直接傳null
;
filename
就可以用來(lái)自定義文件名,因?yàn)?nbsp;file.originalname
也就是上傳的文件的原來(lái)的文件名,其是帶有后綴的,所以我們?cè)谒懊婕觽€(gè)時(shí)間戳來(lái)作為存儲(chǔ)時(shí)的文件名。
現(xiàn)在再次發(fā)送上傳文件請(qǐng)求,存儲(chǔ)到 uploads 目錄下的文件就有帶后綴名了,可以直接在 vscode 打開查看:
上傳多個(gè)文件
如果請(qǐng)求一次性上傳多個(gè)文件,則只需要將 upload.single('file')
替換為 upload.array('files', 3)
即可,傳入?yún)?shù)意為上傳時(shí)文件的 key 為 files(自定義的,也可以是其它名字),并且限制最多上傳 3 張圖片,得到的文件信息可以在下一個(gè)中間件函數(shù)的 req.files
獲取:
app.post('/upload', upload.array('files', 3), (req, res) => { console.log(req.files) res.end('上傳成功') })
當(dāng)我們一次上傳多個(gè)文件時(shí):
打印 req.files
得到的就是個(gè)數(shù)組了:
[ { fieldname: 'files', originalname: '1.png', encoding: '7bit', mimetype: 'image/png', destination: './uploads', filename: '1676958850980-1.png', path: 'uploads\\1676958850980-1.png', size: 904454 }, { fieldname: 'files', originalname: 'qrcode.png', encoding: '7bit', mimetype: 'image/png', destination: './uploads', filename: '1676958850986-qrcode.png', path: 'uploads\\1676958850986-qrcode.png', size: 1076 } ]
將文件部署為靜態(tài)資源
可以使用內(nèi)置的 express.static('./uploads')
中間件函數(shù)將存儲(chǔ)上傳文件的 uploads 目錄設(shè)置為靜態(tài)資源。然后傳給 app.use()
:
app.use(express.static('./uploads'))
這樣我們就可以直接通過(guò)瀏覽器查看上傳得到的文件了,比如 uploads 有張圖片如下:
只需要在瀏覽器輸入 localhost:4396/1677031777791-1.png 即可查看。