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为表单设置的初始值