React之批量上传图片

本文详细介绍了两种批量上传图片的方法:原始input和antd-Upload组件。原始input方式将所有图片一次性提交,而antd-Upload则逐个上传,能跳过不合格图片。文中给出了具体的实现步骤,包括前端页面设置、图片格式校验、后端接口调用等,并对比了两者在处理大量图片时的差异。
摘要由CSDN通过智能技术生成

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

两种方式的区别

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

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


一、原始input

(1)页面使用input HTML

1. 编辑页面元素

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

<Item label={'目标文件'}>
  <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

<Item label={'目标文件'} className={styles['input-upload']}>
  <Upload
    {...uploadProps}
    showUploadList={false} //设置页面不展示上传的文件列表
    directory
    multiple
  >
    <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('上传出错'));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值