React 通过 antd-ui 上传图片使用方法,整理如下

1,603 阅读3分钟

react 安装 antd

npm install antd --save 
或者
yarn antd
电脑有安装yarn可以选择yarn安装

正确的引入 antd 文件 往下翻可以找到 antd 文件代码

index.js.png

index.js引入 antd 文件

import { ConfigProvider, DatePicker, message } from 'antd'; 
// 由于 antd 组件的默认文案是英文,所以需要修改为中文 
import zhCN from 'antd/lib/locale/zh_CN'; 
import moment from 'moment'; 
import 'moment/locale/zh-cn'; 
import 'antd/dist/antd.css'; 
import './index.css'; 
moment.locale('zh-cn');

效果图展示如下

fileup1.png

关于大量的叙述就放在注释当中了,为了降低疑惑,代码为整段写入

可以自行调试修改

import { PlusOutlined, LoadingOutlined } from "@ant-design/icons";
import { Upload, Modal, message, Button } from "antd";
import React, { useState, useMemo } from "react";
import qs from "qs";

// 方法 被away异步调用 执行后return到async异步的同步方法中
function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
  });
}

function TableTwo(props) {
  // 点击编辑或者详情 传递过来的图片数据 保存到state里
  const [ImageUrl, setImageUrl] = useState(
    "http://vueshop.glbuys.com/userfiles/head/590472285.jpeg"
  );

  // 遮罩层的开关state
  const [previewVisible, setpreviewVisible] = useState(false);
  // 遮罩层打开后显示的图片
  const [previewImage, setpreviewImage] = useState("");
  // 遮罩层打开后显示的标题
  const [previewTitle, setpreviewTitle] = useState("");
  // 上传图片左侧弹出的列表 默认number[]
  const [nfileList, setFileList] = useState([]);
  const [loading, setLoading] = useState(false);
  // 上传中...加载状态.....
  const [upImgloading, setUpImgloading] = useState(false);

  // 判断上传图片拦截方法
  const handleChange = ({ file, fileList }) => {
    // { file, fileList }
    // 看官方文档 第一个 file 获取上传文件信息
    // 第二个 fileList 获取的是当前上传成功的图片对象

    // 判断图片格式是否为jpeg
    const isJpgOrPng = file.type === "image/jpeg";
    if (!isJpgOrPng) {
      message.error("文件格式不正确!");
      return isJpgOrPng;
    }

    // 判断图片大小是否小于等于50k
    // 1默认为bit 最小单位
    // 1k = 1b * 1024 b
    // 1m = 1k * 1024 k
    const isLt50K = file.size <= 50 * 1024;
    if (!isLt50K) {
      message.error("文件大小不得超过50k!");
      return isLt50K;
    }

    // 这里才是有趣的地方
    // 当上方拦截器都未触发 则执行此判断
    if (isJpgOrPng && isLt50K) {
      // 首先清空 编辑 或者 详情 传递过来的数据图片地址
      setImageUrl(null);
      // 其次更新上传图片列表 并重新渲染render()
      setFileList(fileList);

      // 如果上传状态为uploading
      if (file.status === "uploading") {
        // 则上传按钮加载中.....
        setUpImgloading(true);
        return;
      }
      // 如果上传状态为done
      if (file.status === "done") {
        // 则上传按钮加载完成
        setUpImgloading(false);
        // 获取上传图片头部url + 图片路径地址
        let url =
          "http://vueshop.glbuys.com/userfiles/head/" +
          file.response.data.msbox;
        // 这里如果表单形式 可以用form回填
        console.log(url);
      }
    }
  };

  //   点击上传时触发事件函数
  const handlePreview = async (file) => {
    //       点击获取本地弹窗 并且获取本地待上传的文件路径
    if (!file.url && !file.preview) {
      // * 个人理解 这里是调用本地弹窗获取本地图片路径 并且上传到file 原型链中
      // 预览的图片 调用异步方法 getBase64 获取到文件详情
      file.preview = await getBase64(file.originFileObj);
    }

    // state存放当前上传图片的地址 或者 图片的预览地址
    setpreviewImage(file.url || file.preview);
    // 是否显示模态框
    setpreviewVisible(true);
    // 模态框标题名字
    setpreviewTitle(
      file.name || file.url.substring(file.url.lastIndexOf("/") + 1)
    );
  };

  // 计算数学缓存传递过来的数据
  useMemo(() => {
    // 获取路由search传递过来的数据 切掉第一个  '/'
    let edit = props.location.search.substr(1);

    // 判断如果存在则执行
    if (edit) {
      // 三目运算符 存在则qs解析出来 不存在则返回{} 原因是form空表单编辑 与 数据点击当前条传递 的区别
      let editVal = edit ? qs.parse(edit) : {};
      // 获取的图片设置到state中 以待使用
      setImageUrl(editVal.img);
    }

    // 这里 [] 填写数据实现动态更新
  }, [props.location.search]);

  // 该方法用于切换上传前 上传后的点击按钮状态
  const uploadButton = (
    <div>
      {upImgloading ? <LoadingOutlined /> : <PlusOutlined />}
      <div style={{ marginTop: 8 }}>点击上传</div>
    </div>
  );

  return (
    <>
      <Upload
        // 图片上传接收的参数
        name="headfile"
        // 图片上传服务器地址
        action="http://vueshop.glbuys.com/api/user/myinfo/formdatahead?token=1ec949a15fb709370f"
        // 图片上传类型
        listType="picture-card"
        //上传列表
        fileList={nfileList}
        // 默认列表只能上传一条 多余的进行覆盖
        maxCount={1}
        //点击触发遮罩层方法 更新遮罩层 图片以及标题
        onPreview={handlePreview}
        //点击触发上传图片方法 判断格式 以及 文件大小 并且 更新上传图片
        onChange={handleChange}
        // 本地弹窗获取本地图片时 可获取的后缀
        accept=".jpg,.jpeg,.png"
        // 可选中多条数据上传
        multiple={true}
      >
        {/* 三目运算符 判断 路由传递的图片是否存在 如果存在则显示 不存在 则显示上传按钮 */}
        {ImageUrl ? (
          <img style={{ width: 100, height: 100 }} src={ImageUrl} alt="" />
        ) : (
          uploadButton
        )}
      </Upload>

      {/* 遮罩层antd */}
      <Modal
        //模态框是否显示
        visible={previewVisible}
        //模态框标题
        title={previewTitle}
        //模态框页脚
        footer={null}
        //模态框点击右上角关闭模态框
        onCancel={() => setpreviewVisible(false)}
      >
        {/* 模态框打开后显示当前点击的图片 */}
        <img alt="example" style={{ width: "100%" }} src={previewImage} />
      </Modal>
      <p>
          {/* 点击清空内容 */}
        <Button
          type="primary"
          style={{ margin: "0 5px" }}
          onClick={() => {
            // 清空路由传递来的图片路径
            setImageUrl();
            // 清空上传图片列表数据
            setFileList([]);
          }}
        >
          取消
        </Button>
      </p>
    </>
  );
}

export default TableTwo;