在现代Web应用开发中,用户界面的交互性和美观性至关重要。特别是对于个人资料页面,一个简洁且功能完备的头像上传组件可以显著提升用户体验。本文将介绍如何使用React结合Ant Design来构建一个支持图片预览、水印添加以及上传进度提示的头像上传组件。

技术栈

  • React: 负责组件化开发。
  • Ant Design: 提供了丰富的UI组件库。
  • FileReader API: 用于读取文件内容并转换为Base64字符串。

功能亮点

  1. 图片格式验证: 只允许上传JPEG或PNG格式的图片。
  2. 大小限制: 图片大小不得超过2MB。
  3. 上传进度指示: 显示上传状态(如加载中、上传完成)。
  4. 图片预览: 实时预览已选择的图片。
  5. 水印添加: 在上传前自动给图片添加指定文字水印

代码解析

首先,我们导入必要的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;

两种上传文件写法,都能上传图片

React和Ant Design实现图片上传功能_上传