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表格数据的格式提交到后端服务器地址。
const SERVER_URL = 'http://localhost:8000'
const UPLOAD_URL = `${SERVER_URL}/upload`
<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'
const SERVER_URL = 'http://localhost:8000'
const UPLOAD_URL = `${SERVER_URL}/upload`
class Example extends Component {
state = {
previewVisible: false,
previewImage: '',
previewImageName: ''
}
showPreview = file => {
this.setState({
previewVisible: true,
previewImage: file.url || file.thumbUrl,
previewImageName: file.name
})
}
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') {
const { ok, message: msg, data } = response
if (ok) {
message.success(msg)
} else {
message.error(msg)
}
}
this.setState({ fileList })
}
那么这样就有了简单的反馈提示:

5. 优化 fileList(可选)
上传了图片后,通过React开发工具插件看看组件状态state,fileList中添加了完整的file对象,我觉得没这个必要吧,因为上传完成后已经用不到里面的一些属性,那么我就在onChange属性对应的函数中手动做个简单的对象添加到fileLIst吧。

写一个optimizeFileList函数吧:
optimizeFileList = (data, fileList) => {
const { name, url } = data
const file = fileList.pop()
const { uid } = 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函数,在函数里向后端发送删除请求,根据后端返回的结果再做处理。
const DELETE_URL = `${SERVER_URL}/delete`
handleRemove = async file => {
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)
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'
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
本文永久链接:https://anandzhang.com/posts/frontend/14