在现代Web应用开发中,用户界面的交互性和美观性至关重要。特别是对于个人资料页面,一个简洁且功能完备的头像上传组件可以显著提升用户体验。本文将介绍如何使用React结合Ant Design来构建一个支持图片预览、水印添加以及上传进度提示的头像上传组件。
技术栈
- React: 负责组件化开发。
- Ant Design: 提供了丰富的UI组件库。
- FileReader API: 用于读取文件内容并转换为Base64字符串。
功能亮点
- 图片格式验证: 只允许上传JPEG或PNG格式的图片。
- 大小限制: 图片大小不得超过2MB。
- 上传进度指示: 显示上传状态(如加载中、上传完成)。
- 图片预览: 实时预览已选择的图片。
- 水印添加: 在上传前自动给图片添加指定文字水印
代码解析
首先,我们导入必要的React Hook以及Ant Design提供的组件:
import React, { useEffect, useState } from 'react';
import { LoadingOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { Flex, message, Upload, Avatar, List } from 'antd';
import React, { useEffect, useState } from 'react';
import { LoadingOutlined, PlusOutlined ,UploadOutlined } from '@ant-design/icons';
import { Flex, message, Upload, Avatar, List } from 'antd';
const props = {
action: 'http://xxx.xx.76.143:48080/admin-api/system/user/profile/update-avatar',
listType: 'picture-circle',
name:"avatarFile",
headers: {
'Authorization':'Bearer '+ localStorage.getItem('token'),
'tenant-id': '1'
},
beforeUpload(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
const img = document.createElement('img');
img.src = reader.result;
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
ctx.fillStyle = '#fff';
ctx.textBaseline = 'middle';
ctx.font = '23px Arial';
ctx.fillText('版权归属woods', 20, 20);
canvas.toBlob((result) => resolve(result));
};
};
});
},
};
const beforeUpload = (file) => {
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png';
if (!isJpgOrPng) {
message.error('You can only upload JPG/PNG file!');
}
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('Image must smaller than 2MB!');
}
return isJpgOrPng && isLt2M;
};
const UserInfo = (userData) => {
const [loading, setLoading] = useState(false);
const [imageUrl, setImageUrl] = useState('');
useEffect(() => {
setImageUrl(userData.data.avatar)
}, [userData])
const handleChange = (info) => {
if (info.file.status === 'uploading') {
setLoading(true);
return;
}
if (info.file.status === 'done') {
}
};
const uploadButton = (
<button
style={{
border: 0,
background: 'none',
}}
type="button"
>
{loading ? <LoadingOutlined /> : <PlusOutlined />}
<div
style={{
marginTop: 8,
}}
>
Upload
</div>
</button>
);
return (
<div>
<Flex gap="middle" wrap>
<Upload
name="avatarFile"
listType="picture-circle"
className="avatar-uploader"
showUploadList={false}
action="http://xxx.xx.76.143:48080/admin-api/system/user/profile/update-avatar"
beforeUpload={beforeUpload}
onChange={handleChange}
headers={{
'Authorization':'Bearer '+ localStorage.getItem('token'),
'tenant-id': '1'
}}
>
{imageUrl ? (
<img src={imageUrl} alt="avatar" style={{ width: '100%', }} />
) : ( uploadButton )}
</Upload>
<Upload {...props}>
{imageUrl ? (
<img src={imageUrl} alt="avatar" style={{ width: '100%', }} />
) : ( uploadButton )}
</Upload>
</Flex>
</div>
);
};
export default UserInfo;
两种上传文件写法,都能上传图片
,