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') //生成隨機(jī)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-08
react在安卓中輸入框被手機(jī)鍵盤遮擋問題的解決方法
這篇文章主要給大家介紹了關(guān)于react在安卓中輸入框被手機(jī)鍵盤遮擋問題的解決方法,文中通過圖文以及示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧2018-09-09
React項目開發(fā)中函數(shù)組件與函數(shù)式編程關(guān)系
函數(shù)組件和函數(shù)式編程究竟是什么關(guān)系呢?本文會圍繞這個話題展開講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11
React實現(xiàn)基于Antd密碼強(qiáng)度校驗組件示例詳解
這篇文章主要為大家介紹了React實現(xiàn)基于Antd密碼強(qiáng)度校驗組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
React之錯誤邊界 Error Boundaries示例詳解
這篇文章主要為大家介紹了React之錯誤邊界Error Boundaries示例教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
React配置Redux并結(jié)合本地存儲設(shè)置token方式
這篇文章主要介紹了React配置Redux并結(jié)合本地存儲設(shè)置token方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01

