React之批量上传图片

文章目录

  • 本文将介绍两种方式进行批量上传图片(原始input/antdUpload)
  • 两种方式的区别
  • 1. 原始input是将图片存为一个对象数组,将不合格的图片过滤掉之后,一次性提交给后端
  • 2. antd-Upload是循环调用后端接口(上传一张的接口)上传图片,遇到不合格的可以跳过
  • 一、原始input
    • (1)页面使用input HTML
      • 1. 编辑页面元素
      • 2. 设置ref
    • (2)编写onChange函数
      • 1. 定义formData
      • 2. 编写onChange函数
      • 3. 上传图片时
      • 4. 图片格式校验函数
    • (3)后端接口
      • 1. 封装好的post
      • 2. 原生post
      • 3. 返回值类型
  • 二、antd-Upload实现批量上传
    • (1)使用antd-Upload的directory方式进行多文件上传
      • 1. html
      • 2. uploadProps
    • (2)对提交的照片进行格式判断和提交给后端
      • 1. 设置图片变量
      • 2. 图片上传函数
    • (3)后端接口

本文将介绍两种方式进行批量上传图片(原始input/antdUpload)

两种方式的区别

1. 原始input是将图片存为一个对象数组,将不合格的图片过滤掉之后,一次性提交给后端

2. antd-Upload是循环调用后端接口(上传一张的接口)上传图片,遇到不合格的可以跳过


一、原始input

(1)页面使用input HTML

1. 编辑页面元素

分别设置type、mutiple,accept,且可以绑定ref


  <div>
    选择图片
    <input
      ref={uploadRef}
      type="file"
      accept="image/*"
      multiple
      onChange={handlePictureChange}
    />
  div>
Item>

2. 设置ref

const uploadRef = useRef<any>();

(2)编写onChange函数

1. 定义formData

  1. 标准形式的formData,但是在使用中需要变成formData.current
const formData = useRef<FormDataProps>(new FormData());
  1. 非标准形式的fromData
  const formData = new FormData();

2. 编写onChange函数

下面使用的是非标准形式的formdata

const handlePictureChange = (e: any): void => {
     
  console.log(uploadRef.current);//通过current可以拿到files
  // debugger;
  //定义fileArr数组将files存入该数组
  const fileArr = [...uploadRef.current.files];
  //对批量上传的图片数量做判断
  if (fileArr.length > 200) {
     
    message.error('图片数量较多');
  } else {
     
    fileArr.forEach((item: any, index: any) => {
     
    //这是我编写的验证图片格式函数,下面会介绍
      const picType = judgePictureType(item.type);
      if (picType) {
     
        //图片格式正确
        formData.append('file', item)
      } else {
     
        message.error('请确保图片格式正确!');
      }
    });
    //下面这段代码可以看到格式正确,且存入了formData
    // formData.forEach((value: any, key: any) => {
     
    //   console.log(value, key);
    // });
  }
};

3. 上传图片时

当点击页面的提交button时,下面使用的标准形式的formData

const handleSubmit: React.FormEventHandler<HTMLFormElement> = useCallback(
    (e): void => {
     
      e.preventDefault();
      validateFields(async (err, values) => {
     
      //判断formdata是否为空
        if (!err && formData.current.get('file')) {
     
          try {
     
            // 可以看见formData 的值
            formData.current.forEach((value: any, key: any) => {
     
              console.log(value, key);
            });
   			//后端接口
            piliaruku(formData.current);
            
          } catch (e) {
     
            message.error(e.message || '添加失败');
          }
        } else {
     
          message.error('提交格式有误!');
        }
      });
    },
    [formData, validateFields],
  );

4. 图片格式校验函数

export function judgePictureType(type: string): boolean {
     
  const isJPG = type === 'image/jpeg';
  const isPNG = type === 'image/png';
  const isBMP = type === 'image/bmp';
  const isPic = isJPG || isPNG || isBMP;
  return isPic ? true : false;
}

(3)后端接口

此时,不能使用封装好的post,需要使用axios.post

1. 封装好的post

export async function post<R = any, P = any>(
  url: string,
  data?: P,
  config?: AxiosRequestConfig,
): Promise<ResponseReturn<R>> {
     
  const response = await http.post(url, data, config);
  return response.data;
}

2. 原生post

import axios from 'axios';
export async function piliaruku(params: any): Promise<ResponseReturn<PliliangrukuResponse>> {
     
  return await axios.post('/piliangruku', params, {
     
  //设置批量上传的请求头
    headers: {
     
      'Content-Type': 'multipart/form-data',
    },
  });
}

3. 返回值类型

export type PliliangrukuResponse = null;

二、antd-Upload实现批量上传

(1)使用antd-Upload的directory方式进行多文件上传

1. html


  
    <Button>
      <Icon type="upload" /> 请选择文件夹
    Button>
  Upload>
Item>
<Form.Item>
 <Button type="primary" htmlType="submit" loading={loading}>
    {loading ? '上传中,请不要重复提交' : '提交'}
  Button>
Form.Item>

2. uploadProps

在这里使用beforeUpload对图片做格式判断没有任何意义,如果在uploadProps使用上传函数接口,不管是在beforeUpload还是onChange,都会上传。
举个例子,假如要求图片不超过200,你可以在beforeUpload中使用fileList进行判断,但是如果文件夹中有260张,但其实还是对260张进行了暂存。也就是说循环上传无法停止。

const file_list = useRef<any>([]);
 const uploadProps = {
     
  accept: 'image/*',
  beforeUpload(): boolean {
     
    return false;
  },
  async onChange(info: UploadChangeParam<UploadFile<any>>): Promise<void> {
     
    if (!info.file) return Promise.reject(new Error('请选择图片'));
    try {
     
      file_list.current = info.fileList;
    } catch (e) {
     
      console.error(e);
    }
  },
};

(2)对提交的照片进行格式判断和提交给后端

1. 设置图片变量

const [loading, setLoading] = useState(false); //loading状态
const [fileNum, setFileNum] = useState(0); //文件总数
const [fileSuccessNum, setFileSuccessNum] = useState(0);//文件成功的数量

2. 图片上传函数

const handleSubmit: React.FormEventHandler<HTMLFormElement> = useCallback((e): void => {
     
    e.preventDefault();
    setLoading(true); //图片上传开始
    if (file_list.current.length > 200) {
     
      message.error('图片数量较多');
      return;
    }
    const fileArr: Promise<ResponseReturn<PliliangrukuResponse>>[] = [];
    file_list.current.forEach((file: any) => {
     
      const reg = /(\.png|\.jpg|\.jpeg)$/g;
      //判断格式
      if (!reg.test(file.name)) {
     
      //我这里设置了一个变量将格式不正确的图片存入这个数组中
        const messageErr = file.name + ' 格式不正确';
        setErrFile(errFile => [...errFile, messageErr]);
      } else {
     
        const formData = new FormData();
        formData.append('file', file.originFileObj);
        //后端接口
        fileArr.push(pilianrukuXunhuan(formData));
      }
    });
    setFileNum(fileArr.length); //总数
    Promise.all(fileArr)
      .then(res => {
     
        setFileSuccessNum(res.length); //上传成功的数量
        setLoading(false); //图片上传结束
        setConfirmModal(true);
      })
      .catch(e => {
     
        message.error(e);
      })
      .finally(() => {
     
        setLoading(false);//图片上传失败的状态
      });
  }, []);

(3)后端接口

因为图片上传函数使用了promise封装,所以对后端提交函数做了部分修改

export async function pilianrukuXunhuan(params: any): Promise<ResponseReturn<PliliangrukuResponse>> {
     
  const res: any = await axios.post('/..../piliangruku', params, {
     
    headers: {
     
      'Content-Type': 'multipart/form-data',
    },
  });
  if (res.status === 200 && res.data.code === 0) {
     
    return Promise.resolve(res.data);
  }
  return Promise.reject(new Error('上传出错'));
}

你可能感兴趣的:(react,javascript,js,react)