React + Node.js实现图片上传功能
作者:JacksonChen_
效果
技术栈
前端:react+antdesign(upload组件)
后端:node+express+multer+uuid
前端
上传前
这边前端直接使用的 antdesign 所提供的上传组件,代码如下
<Upload accept="multipart/form-data" name="avater" listType="picture-card" fileList={[]} // 手动设置空的 fileList className="avatar-uploader" showUploadList={false} beforeUpload={(file) => { handlePreview(file) return false // 阻止默认上传行为 }} > {imageUrl ? <img src={imageUrl} alt="avater" style={{ width: '100%' }} /> : uploadButton} </Upload>
accept="multipart/form-data:是用于指定在 HTML 表单中上传文件时使用的编码类型。它告诉服务器将表单数据编码为 multipart/form-data
格式,这是用于上传文件的一种常见方式。
beforeUpload:则是需要在上传前对文件进行处理,我们来看一下代码里面发生了什么。
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('图片预览失败', error) message.error('图片预览失败') 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 }
如果是图片类型则创建一个新的FileReader
对象。
reader.readAsDataURL(file)
开始读取指定的文件,这里的 file
是一个文件对象,通过某种方式传递给这段代码。readAsDataURL
方法会将文件内容读取为Data URL。
reader.onload:
设置一个事件处理程序,当文件读取完成时会触发该事件。
在读取完成时,触发 onload
事件。在这个函数中,通过 reader.result
获取读取到的Data URL,然后使用 setImageUrl 函数将其反显到页面当中。
const reader = new FileReader() reader.onload = () => { setImageUrl(reader.result as string) setLoading(false) } reader.readAsDataURL(file)
这段上传前的代码是为了判断是否为图片类型,以及读取出来图片反显到页面当中,大家根据自己的需求调整。
反显效果如下:
上传
上传前准备工作以就绪,接下来就是点击上传,注意我这里因为有其他信息,需要一起上传。
如果只是单独的上传图片一个功能,antdesign 提供的有现成的代码,只需要在action属性写上后端地址即可。
点击上传
我们使用 antdesign 的表单提交功能,点击上传后得到一个values对象如下:
我们的图片信息在pic字段下,这个字段是自己设置的,下面是点击上传文件相关代码。
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) => { }) }
首先创建一个新的 FormData
对象,用于构建表单数据。
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中发给后端即可!
后端
首先安装相关模块
npm i express //用于接口请求 npm i multer //文件模块 npm i uuid //文件命名
指定静态页面(图片存储文件夹)
app.use('/uploads/', express.static('./uploads')) //指定静态页面
解析Body数据
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())//存储的文件名 }, })
使用配置好的存储创建multer实例
const upload = multer({ storage: storage })
定义一个用于添加文章的路由,支持文件上传
使用 upload.single('file')
作为中间件来处理带有字段名 'file' 的单个文件上传,这与上面前端上传的命名相对应( 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文件夹中
完整代码
由于整个项目不单单是这一个功能,这里就把上传图片功能所用到的前后端代码进行分享,有需要的同学可以参考一下代码!
前端
HTML <Upload accept="multipart/form-data" name="avater" listType="picture-card" fileList={[]} // 手动设置空的 fileList className="avatar-uploader" showUploadList={false} beforeUpload={(file) => { handlePreview(file) return false // 阻止默认上传行为 }} > {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('图片预览失败', error) message.error('图片预览失败') 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')) //指定静态页面 //解析Body数据 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实现图片上传功能的详细内容,更多关于React+Node.js图片上传的资料请关注脚本之家其它相关文章!