React + Node.js實現(xiàn)圖片上傳功能
效果
技術(shù)棧
前端:react+antdesign(upload組件)
后端:node+express+multer+uuid
前端
上傳前
這邊前端直接使用的 antdesign 所提供的上傳組件,代碼如下
<Upload accept="multipart/form-data" name="avater" listType="picture-card" fileList={[]} // 手動設(shè)置空的 fileList className="avatar-uploader" showUploadList={false} beforeUpload={(file) => { handlePreview(file) return false // 阻止默認(rèn)上傳行為 }} > {imageUrl ? <img src={imageUrl} alt="avater" style={{ width: '100%' }} /> : uploadButton} </Upload>
accept="multipart/form-data:是用于指定在 HTML 表單中上傳文件時使用的編碼類型。它告訴服務(wù)器將表單數(shù)據(jù)編碼為 multipart/form-data
格式,這是用于上傳文件的一種常見方式。
beforeUpload:則是需要在上傳前對文件進(jìn)行處理,我們來看一下代碼里面發(fā)生了什么。
const handlePreview = async (file: File) => { setImageUrl('') setLoading(true) const isImage = file.type.startsWith('image/') const isImageExtension = /\.(jpg|jpeg|png|gif)$/i.test(file.name) if (!isImage || !isImageExtension) { message.error(`${file.name} is not a supported image file`) return Upload.LIST_IGNORE } try { const reader = new FileReader() reader.onload = () => { setImageUrl(reader.result as string) setLoading(false) } reader.readAsDataURL(file) } catch (error) { console.error('圖片預(yù)覽失敗', error) message.error('圖片預(yù)覽失敗') setLoading(false) } }
首先判斷文件的格式是不是圖片類型的,如果不是,則終止上傳。
const isImage = file.type.startsWith('image/') const isImageExtension = /\.(jpg|jpeg|png|gif)$/i.test(file.name) if (!isImage || !isImageExtension) { message.error(`${file.name} is not a supported image file`) return Upload.LIST_IGNORE }
如果是圖片類型則創(chuàng)建一個新的FileReader
對象。
reader.readAsDataURL(file)
開始讀取指定的文件,這里的 file
是一個文件對象,通過某種方式傳遞給這段代碼。readAsDataURL
方法會將文件內(nèi)容讀取為Data URL。
reader.onload:
設(shè)置一個事件處理程序,當(dāng)文件讀取完成時會觸發(fā)該事件。
在讀取完成時,觸發(fā) onload
事件。在這個函數(shù)中,通過 reader.result
獲取讀取到的Data URL,然后使用 setImageUrl 函數(shù)將其反顯到頁面當(dāng)中。
const reader = new FileReader() reader.onload = () => { setImageUrl(reader.result as string) setLoading(false) } reader.readAsDataURL(file)
這段上傳前的代碼是為了判斷是否為圖片類型,以及讀取出來圖片反顯到頁面當(dāng)中,大家根據(jù)自己的需求調(diào)整。
反顯效果如下:
上傳
上傳前準(zhǔn)備工作以就緒,接下來就是點擊上傳,注意我這里因為有其他信息,需要一起上傳。
如果只是單獨的上傳圖片一個功能,antdesign 提供的有現(xiàn)成的代碼,只需要在action屬性寫上后端地址即可。
點擊上傳
我們使用 antdesign 的表單提交功能,點擊上傳后得到一個values對象如下:
我們的圖片信息在pic字段下,這個字段是自己設(shè)置的,下面是點擊上傳文件相關(guān)代碼。
const handleAddRequest = async (values: any) => { const formData = new FormData() if (values.pic && values.pic.fileList.length) { const file = values.pic.fileList[0].originFileObj formData.append('file', file, values.pic.fileList[0].name) } fetch(baseUrl + '/add-article', { method: 'POST', body: formData, }) .then((res) => res.json()) .then((res) => { }) .catch((error) => { }) }
首先創(chuàng)建一個新的 FormData
對象,用于構(gòu)建表單數(shù)據(jù)。
const formData = new FormData()
檢查是否存在圖片信息(values.pic
),并且圖片文件列表(values.pic.fileList
)不為空。
values.pic.fileList[0].originFileObj
則是獲取這個文件對象的原始文件對象。
將文件添加到 FormData
。
const file = values.pic.fileList[0].originFileObj formData.append('file', file, values.pic.fileList[0].name)
注意 'file' 需要和后端讀取文件的命名一致,等會后端會介紹。
最后只需要將整理好的formData對象放到body中發(fā)給后端即可!
后端
首先安裝相關(guān)模塊
npm i express //用于接口請求 npm i multer //文件模塊 npm i uuid //文件命名
指定靜態(tài)頁面(圖片存儲文件夾)
app.use('/uploads/', express.static('./uploads')) //指定靜態(tài)頁面
解析Body數(shù)據(jù)
const bodyParser = require('body-parser') app.use(bodyParser.json())
配置 multer 磁盤存儲
const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads/')//圖片要存儲的文件夾地址 }, filename: function (req, file, cb) { cb(null, uuid.v1() + '.' + file.originalname.split('.').pop())//存儲的文件名 }, })
使用配置好的存儲創(chuàng)建multer實例
const upload = multer({ storage: storage })
定義一個用于添加文章的路由,支持文件上傳
使用 upload.single('file')
作為中間件來處理帶有字段名 'file' 的單個文件上傳,這與上面前端上傳的命名相對應(yīng)( formData.append('file', file, values.pic.fileList[0].name))
app.post('/add-article', upload.single('file'), async (req, res) => { const filePath = 'uploads/' + req.file.filename // 獲取上傳文件存儲的文件路徑 //todo.... })
最后上傳的圖片會存到uploads文件夾中
完整代碼
由于整個項目不單單是這一個功能,這里就把上傳圖片功能所用到的前后端代碼進(jìn)行分享,有需要的同學(xué)可以參考一下代碼!
前端
HTML <Upload accept="multipart/form-data" name="avater" listType="picture-card" fileList={[]} // 手動設(shè)置空的 fileList className="avatar-uploader" showUploadList={false} beforeUpload={(file) => { handlePreview(file) return false // 阻止默認(rèn)上傳行為 }} > {imageUrl ? <img src={imageUrl} alt="avater" style={{ width: '100%' }} /> : uploadButton} </Upload> JS ##上傳前操作 const handlePreview = async (file: File) => { setImageUrl('') setLoading(true) const isImage = file.type.startsWith('image/') const isImageExtension = /\.(jpg|jpeg|png|gif)$/i.test(file.name) if (!isImage || !isImageExtension) { message.error(`${file.name} is not a supported image file`) return Upload.LIST_IGNORE } try { const reader = new FileReader() reader.onload = () => { setImageUrl(reader.result as string) setLoading(false) } reader.readAsDataURL(file) } catch (error) { console.error('圖片預(yù)覽失敗', error) message.error('圖片預(yù)覽失敗') setLoading(false) } } ##上傳處理字段 const handleAddRequest = async (values: any) => { const formData = new FormData() if (values.pic && values.pic.fileList.length) { const file = values.pic.fileList[0].originFileObj formData.append('file', file, values.pic.fileList[0].name) } fetch(baseUrl + '/add-article', { method: 'POST', body: formData, }) .then((res) => res.json()) .then((res) => { }) .catch((error) => { }) }
后端
const express = require('express') const multer = require('multer') //文件上傳模塊 const uuid = require('uuid') //生成隨機uuid-圖片命名需要 app.use('/uploads/', express.static('./uploads')) //指定靜態(tài)頁面 //解析Body數(shù)據(jù) const bodyParser = require('body-parser') app.use(bodyParser.json()) const storage = multer.diskStorage({ destination: function (req, file, cb) { cb(null, 'uploads/') }, filename: function (req, file, cb) { cb(null, uuid.v1() + '.' + file.originalname.split('.').pop()) }, }) const upload = multer({ storage: storage }) // 新增文章 app.post('/add-article', upload.single('file'), async (req, res) => { const filePath = 'uploads/' + req.file.filename//存儲的文件名 todo..... })
以上就是React + Node.js實現(xiàn)圖片上傳功能的詳細(xì)內(nèi)容,更多關(guān)于React+Node.js圖片上傳的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
react項目升級報錯,babel報錯,.babelrc配置兼容等問題及解決
這篇文章主要介紹了react項目升級報錯,babel報錯,.babelrc配置兼容等問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08React項目開發(fā)中函數(shù)組件與函數(shù)式編程關(guān)系
函數(shù)組件和函數(shù)式編程究竟是什么關(guān)系呢?本文會圍繞這個話題展開講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11React實現(xiàn)基于Antd密碼強度校驗組件示例詳解
這篇文章主要為大家介紹了React實現(xiàn)基于Antd密碼強度校驗組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01React之錯誤邊界 Error Boundaries示例詳解
這篇文章主要為大家介紹了React之錯誤邊界Error Boundaries示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10React配置Redux并結(jié)合本地存儲設(shè)置token方式
這篇文章主要介紹了React配置Redux并結(jié)合本地存儲設(shè)置token方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01