Antd 4 Upload 图片上传(前端篇)
简介
记录一下第一次使用Ant Design
的Upload
组件上传图片到后端服务器的基本流程和思路。
前端使用了React + Antd
,后端使用Nodejs
的Express
。
主要介绍Antd
中Upload
组件的照片墙,也就是上传多张图片。
Ant Design
官方Upload
教程地址:Antd Upload 组件
实现
1. 简单的render
import React, { Component } from 'react'
import { Card, Upload } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
class Example extends Component {
render() {
return (
<Card title='图片上传'>
<Upload listType='picture-card'>
<PlusOutlined />
<div style={{ marginTop: 8, color: '#666' }}>上传图片</div>
</Upload>
</Card>
)
}
}
export default Example
也就是先做一个基本的Upload
组件样子:
Card
组件是为了案例的样式效果好一点。现在的Upload
组件还不具有上传的功能,只是简单的使用,listType
属性是Upload
组件的显示效果,有picture-card
、picture
、text
这三个属性值,对应的效果可在Antd
官网查看。
2. 上传功能
给Upload
组件添加action
属性,就可以利用FormData
表格数据的格式提交到后端服务器地址。
// 省略部分代码
// 后端API
const SERVER_URL = 'http://localhost:8000'
const UPLOAD_URL = `${SERVER_URL}/upload`
// render 中部分代码
<Upload
listType='picture-card'
action={UPLOAD_URL}
>
<PlusOutlined />
<div style={{ marginTop: 8, color: '#666' }}>上传图片</div>
</Upload>
3. 查看图片
- 添加一个用于查看图片的
Modal
对话框组件,设置组件的footer
属性为null
来隐藏对话框对应的确认和取消按钮;然后在Modal
组件中包含一个原生的img
标签用来显示图片,设置对应的src
和alt
属性。 - 在
Upload
组件中设置onPreview
属性,用户点击查看图片按钮就会触发这个函数。在onPreview
中设置组件的几个状态。
import React, { Component } from 'react'
import { Card, Upload, Modal } from 'antd'
import { PlusOutlined } from '@ant-design/icons'
// 后端API
const SERVER_URL = 'http://localhost:8000'
const UPLOAD_URL = `${SERVER_URL}/upload`
class Example extends Component {
state = {
previewVisible: false,
previewImage: '',
previewImageName: ''
}
// 显示用于查看图片的 Modal 组件
showPreview = file => {
this.setState({
previewVisible: true,
previewImage: file.url || file.thumbUrl,
previewImageName: file.name
})
}
// 隐藏用于查看图片的 Modal 组件
hidePreview = () => {
this.setState({
previewVisible: false
})
}
render() {
const { previewVisible, previewImage, previewImageName } = this.state
return (
<Card title='图片上传'>
<Upload
listType='picture-card'
action={UPLOAD_URL}
onPreview={this.showPreview}
>
<PlusOutlined />
<div style={{ marginTop: 8, color: '#666' }}>上传图片</div>
</Upload>
{/* 用于查看图片的 Modal 对话框 */}
<Modal
visible={previewVisible}
footer={null}
onCancel={this.hidePreview}
>
<img
src={previewImage}
alt={previewImageName}
style={{ width: '100%' }}
/>
</Modal>
</Card>
)
}
}
export default Example
4. 处理服务端上传结果
前面实现的上传图片,虽然通过action
属性向服务端发送了请求,但是我们并没有对服务端返回的上传结果进行处理。也就是说,我们没有将服务端的结果反馈给用户,用户并不清楚服务端是否也上传成功,图片是否成功存在服务端。
首先给Upload
组件添加onChange
属性:onChange={this.handleChange}
。然后我们定义handleChange
函数:
// 处理图片上传
handleChange = ({ file, fileList }) => {
const { status, response } = file
// 上传完成?
if (status === 'done') {
// 服务端返回JSON:{ok: true/false, message: "", data: ""}
const { ok, message: msg, data } = response
if (ok) {
// antd的message方法
message.success(msg)
} else {
message.error(msg)
}
}
this.setState({ fileList })
}
那么这样就有了简单的反馈提示:
5. 优化 fileList(可选)
上传了图片后,通过React
开发工具插件看看组件状态state
,fileList
中添加了完整的file
对象,我觉得没这个必要吧,因为上传完成后已经用不到里面的一些属性,那么我就在onChange
属性对应的函数中手动做个简单的对象添加到fileLIst
吧。
写一个optimizeFileList
函数吧:
// fileList中file文件对象的属性太多了,上传完成后只留必要的属性
optimizeFileList = (data, fileList) => {
// 后端数据中取得图片的名称和url地址
const { name, url } = data
// 去除上传完成后自动添加到fileList的file对象
const file = fileList.pop()
// 拿到需要的uid
const { uid } = file
// 创建一个只有必须属性的file对象
const newFile = { uid, name, url: `${SERVER_URL}/${url}` }
fileList.push(newFile)
}
// 处理图片上传
handleChange = ({ file, fileList }) => {
const { status, response } = file
// 上传成功?
if (status === 'done') {
const { ok, message: msg, data } = response
if (ok) {
this.optimizeFileList(data, fileList)
message.success(msg)
} else {
message.error(msg)
}
}
this.setState({ fileList })
}
现在上传图片后我们看一下组件的state
,只保留了uid
、name
、url
:
6. 删除功能
点击删除时不只是清除state
就完了,还需要删除服务端存的图片。设置onRemove
属性绑定handleRemove
函数,在函数里向后端发送删除请求,根据后端返回的结果再做处理。
// 添加一个后端API
const DELETE_URL = `${SERVER_URL}/delete`
// 类组件中:
handleRemove = async file => {
// 有url属性说明上传到了服务器
const { url } = file
if (url) {
const path = url.replace(`${SERVER_URL}/`, '')
const response = await fetch(DELETE_URL, {
method: 'delete',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ path })
})
const { ok, message: msg } = await response.json()
if (ok) {
message.success(msg)
} else {
message.error(msg)
return false
}
}
}
补充:Form自动收集Upload数据
在Form
组件中使用Uploda
组件让用户上传图片,在表单提交的时候我们也想让Form
自动收集到Upload
组件的数据,我们需要配合Form
组件提供给子组件props
中的onChange
方法来完成。
1. 修改 Upload 组件
在Upload
组件的onChange
属性绑定的handleChange
方法中调用props
的onChange
方法:
handleChange = ({ file, fileList }) => {
const { status, response } = file
// 上传成功?
if (status === 'done') {
const { ok, message: msg, data } = response
if (ok) {
this.optimizeFileList(data, fileList)
// 调用 onChange 方法
this.props.onChange(fileList)
message.success(msg)
} else {
message.error(msg)
}
}
this.setState({ fileList })
}
2. 在 Form 组件中使用 Upload
import React, { Component } from 'react'
import { Card, Form, Input, Button } from 'antd'
// 引入写好的Upload组件
import UploadImage from './UploadImage'
const { Item } = Form
class FormExample extends Component {
handleSubmit = values => {
console.log(values)
}
render() {
return (
<Card title='表单案例'>
<Form onFinish={this.handleSubmit}>
<Item label='商品名称' name='name'>
<Input />
</Item>
<Item label='商品图片' name='images'>
<UploadImage />
</Item>
<Button type='primary' htmlType='submit'>提交</Button>
</Form>
</Card>
)
}
}
export default FormExample
提交数据我们就收集到Upload
组件的fileList
数据,然后自己用需要的数据提交给后端就OK。
版权声明:
Anand's Blog文章皆为站长Anand Zhang原创内容,转载请注明出处。
包括商业转载在内,注明下方要求的文章出处信息即可,无需联系站长授权。
请尊重他人劳动成果,用爱发电十分不易,谢谢!
请注明出处:
本文出自:Anand's Blog