antd5 form表单编辑图片/文件提交

401 阅读1分钟

react18+antd5实现form编辑时先上传图片(文件)获取地址后随表单提交到后端

背景:日常运营后台中时常涉及到上传图片或者上传文件,编辑更改图片后提交表单为更改后的上传地址

首先对于upload组建的封装

重点在于对onchange事件的处理

    import React, { useEffect, useState } from "react";
    import { Upload, notification } from 'antd';
    import { PlusOutlined, LoadingOutlined, DeleteOutlined } from '@ant-design/icons';
    import {UploadChangeParam, RcFile} from "antd/es/upload/interface";
    
    interface UploadProps {
        value?: any;
        onChange?: (value: any) => void;
        originUrl?: string;
        isBigFile?: boolean;
        disabled?: boolean;
        isCompress?: boolean;
        maxWidthOrHeight?: number;
        children?: any;
    }
    
    export const FormImgUpload: React.FC<UploadProps> = ({ children, onChange, originUrl='', isCompress, maxWidthOrHeight }) => {

        const [loading, setLoading] = useState(false);
        const [imageUrl, setImageUrl] = useState<string | ArrayBuffer | null>(originUrl);
        const [fileLists, setFileList] = useState<any>([]);

        useEffect(() => {
          if(originUrl) {
            setFileList([{
              imgUrl: originUrl,
              url: originUrl,
              status: 'done',
              name: 'image.png',
              uid: originUrl
            }])
          }
        }, [originUrl])
    
        const triggerChange = (changedValue: any) => {
            if (onChange) {
              onChange({...changedValue});
            }
        };

        const beforeImageUpload = (file: RcFile, fileList: RcFile[]) => {
          return new Promise(async (resolve, reject) => {
            const file_ = await readImg(file);
            const newFile = await compressImg(file_, file.type)
            resolve(newFile)
          })
        };
  

        const handleChange = (info: UploadChangeParam) => {
          const { file } = info;
          let { fileList: files } = info;
          files = files.map((e_file: any) => {
            if (e_file.response) {
              e_file.id = e_file.uid;
              e_file.imgUrl = e_file.response.data.fileUrl //请求之后返回的key
            }
            return e_file;
          });
          if (file.status) {
            if (file.status === 'done') {
              const response = info.file.response;
              const { code, msg, data } = response;
              if(code !== 'A00000') {
                notification.open({
                  message: '上传出错',
                  description: msg
                });
                setLoading(false);
                return;
              }
              triggerChange(data);
              // triggerChange(files);
            } else if (file.status === 'error') {
              console.log('上传失败')
            } else if (file.status === 'removed') {
              triggerChange({});
            }
        }
          setFileList([...files]);
        };

        const uploadButton = (
          <div>
              {/* {loading ? <LoadingOutlined/> : <PlusOutlined/>} */}
              <PlusOutlined />
              <div style={{marginTop: 8}}> {children} </div>
          </div>
        );

        return (
            <Upload
              name="file"
              listType="picture-card"
              className="uploader"
              fileList={fileLists}
              beforeUpload={(file, fileList) => {
                const fileName = file.name.split('.')[0];
                return new Promise(async (resolve, reject) => {
                  if(isCompress) {
                    const file_ = await readImg(file);
                    const newFile:any = await compressImg(file_, file.type, fileName, maxWidthOrHeight)
                    resolve(newFile)
                  } else {
                    resolve(file);
                  }
                })
              }}
              action={`${upload_url}`}
              onChange={handleChange}
              data={{is_big_file: false}}
              accept="image/gif,image/jpeg,image/jpg,image/png,image/svg"
            >
              {fileLists.length > 0 ? null : uploadButton}
            </Upload>
        );
}
使用如下
      <Form.Item label='icon' name="icon_url"
           valuePropName="icon_url"
           getValueFromEvent={(info) => normFile(info)}
           shouldUpdate={true}
           labelCol={{ span: 8 }}
           wrapperCol={{ span: 12 }}
           rules={[{ required: true, message: '请上传Icon' }]}
       >
           <FormImgUpload originUrl={initialValues.icon_url}>upload</FormImgUpload>
      </Form.Item>
      
      const normFile = ({ fileUrl }: any) => {
        return fileUrl;
      };

其中initialValues为表单设置的初始值

文件上传类似,核心在于对onchange事件的处理