react项目上传文件

1. antd design组件为例(附源码)

iview 的upload组件可能一些api和属性会有一些变化,但大体类似

2. 应用场景

官网给出的示例,其主要应用场景为通过设置action(文件上传url),单独上传文件,官网给出的相关方法和属性都是基于设置action单独上传文件实现的。但有时候我们的需求是上传表单数据和文件列表到一个接口而不是设置action单独上传文件,这时候官网给出的例子可能就不能直接使用,需要一定的改变,本篇文章就是基于这样的前端需求产生的。以下为官网给出的示例:

import { Upload, message, Button } from 'antd';
import { UploadOutlined } from '@ant-design/icons';

const props = {
  name: 'file',
  action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
  headers: {
    authorization: 'authorization-text',
  },
  onChange(info) {
    if (info.file.status !== 'uploading') {
      console.log(info.file, info.fileList);
    }
    if (info.file.status === 'done') {
      message.success(`${info.file.name} file uploaded successfully`);
    } else if (info.file.status === 'error') {
      message.error(`${info.file.name} file upload failed.`);
    }
  },
};

ReactDOM.render(
  <Upload {...props}>
    <Button icon={<UploadOutlined />}>Click to Upload</Button>
  </Upload>,
  mountNode,
);

3. 主要实现功能

  1. 规定允许上传文件格式以及文件数量
  2. 删除文件实现
  3. 获取文件列表通过axios上传文件列表

4. 前期准备

  1. create-react-app创建react项目
  2. 安装antd-design、axios
    安装相关依赖版本:
    “antd”: “^4.19.3”,
    “axios”: “^0.26.1”,

5. 主要实现代码

// upload组件使用
import { Button, Form, Upload, message } from "antd";
import { UploadOutlined } from "@ant-design/icons";
import {
  upload,
} from "@/api/upload.js"; //引入上传的接口
import { useState, useEffect} from "react";
/*定义允许上传的文件后缀*/
const filePostfix =
  "'jpg', 'jpeg', 'png','bmp','svg','gif', 'doc','docx', 'xls', 'xlsx', 'ppt','pptx','pdf'";

function Upload() {
  const [form] = Form.useForm();
  //上传文件列表
  const [fileList, setFileList] = useState([]);
  // 文件上传预处理事件
  const beforeUploadHandler = (file) => {
    let splitByDot = file.name.split(".");
    //取最后一个“.”后的内容:1.1.jpg
    let postfix = splitByDot[splitByDot.length - 1];
    const check = fileList.length < 10;
    // 控制上传文件类型
    if (!check) {
      message.warning("最多上传十个文件");
    } else {
      if (filePostfix.indexOf(postfix) > -1) {
        fileList.push(file);
      } else {
        message.warning(
          "文件格式不正确: 仅支持图片、word、ppt、excel类型的文件!"
        );
      }
    }
    return false;
  };
  // 删除文件处理事件
  const handleRemove = (file) => {
    let idx = fileList.indexOf(file);
    let arr = [];
    for (let i = 0; i < fileList.length; i++) {
      arr[i] = fileList[i];
    }
    while (idx !== fileList.length - 1) {
      arr[idx] = fileList[idx + 1];
      idx++;
    }
    if (idx == fileList.length - 1) {
      arr.pop();
    }
    setFileList(arr);
    return true;
  };

  const onFinish = (val) => {
    console.log("success");
    console.log(val);
  };
  const onFinishFailed = (errInfo) => {
    console.log(errInfo);
  };
  const upload = () => {
    let params = form.getFieldValue();
    let uploadParams = { ...params };
     uploadFiles(uploadParams );
  };
  const uploadFiles= (params) => {
    let formData = new FormData();
    fileList.forEach((file, index) => {
    // multipartFiles为上传的文件参数名
      formData.append("multipartFiles", file);
    });
    let reqParams = {
    //具体请求参数根据接口要求改变
      method: "post",
      params: {
        ...params, // 其他表单参数
      },
      data: formData,
    };
    upload(reqParams)
      .then((res) => {
        if (res.data.code == 200) {
          message.success(res.data.message);
          form.resetFields(); // 表单数据清空
          setFileList([]); // 文件列表清空
        } else {
          message.error(res.data.message);
        }
      })
      .catch((error) => {
        console.log(error);
      });
  };
  const clear = () => {
    form.resetFields();
  };

  return (
    <div>
          <Form
            form={form}
            onFinish={onFinish}
            onFinishFailed={onFinishFailed}
            labelAlign="right"
            labelWrap={true}
            labelCol={{ span: 4 }}
            wrapperCol={{ span: 20 }}
          >
            <Form.Item>
              <div>
                <Upload
                  action=""
                  accept={filePostfix}
                  multiple
                  fileList={fileList}
                  beforeUpload={beforeUploadHandler}
                  showUploadList={true}
                  onRemove={handleRemove}
                >
                  <Button
                    icon={<UploadOutlined />}
                    className={dongdongStyles.upload}
                  >
                    点击上传
                  </Button>
                </Upload>
              </div>
            </Form.Item>
            <Form.Item>
              <div style={{ marginBottom: "10px" }}>
                <Button type="primary" onClick={upload}>
                  提交
                </Button>
                <Button onClick={clear} style={{ marginLeft: "5px" }}>
                  重置
                </Button>
              </div>
            </Form.Item>
          </Form>
        </div>
  );
}

export default Upload;

axios上传文件对应参考博客:

6. 遇到问题及解决

点击删除文件图标后,文件列表删除了该文件,但下方上传文件列表处仍显示该文件,刷新文件删除:
这块之前是直接更新fileList的值,而非通过setFileList方法更新fileList的值,所以,fileList值变了但当前状态下fileList的值还是原先的值,所以删除的文件列表仍存在,这里应该通过setFileList更新fileList的值。
正确代码如下:

 // 删除文件处理事件
  const handleRemove = (file) => {
    let idx = fileList.indexOf(file);
    let arr = [];
    for (let i = 0; i < fileList.length; i++) {
      arr[i] = fileList[i];
    }
    while (idx !== fileList.length - 1) {
      arr[idx] = fileList[idx + 1];
      idx++;
    }
    if (idx == fileList.length - 1) {
      arr.pop();
    }
    setFileList(arr);
    return true;
  };

7. axios上传文件

详见axios请求

你可能感兴趣的:(axios,upload组件,前端)