Ant Design 自定义文件上传组件
为了在 Ant Design 的表单中实现自定义文件上传功能,可以通过封装一个独立的上传组件,并将其与表单字段(FormItem)集成。以下代码展示了如何实现这一功能。
首先,创建一个名为 CustomFileUploader 的 React 组件:
import React from 'react';
import { Upload, Button, message } from 'antd';
import { uploadService, queryService } from '@/services/fileUpload';
class CustomFileUploader extends React.Component {
constructor(props) {
super(props);
this.state = {
uploadedFiles: [],
fileRecords: []
};
this.isInitialValueEmpty = true;
}
componentDidMount() {
this.syncWithInitialValue();
}
syncWithInitialValue = () => {
const { initialValue } = this.props['data-__meta'] || {};
if (initialValue !== this.currentInitialValue) {
this.handleInitialValueChange(initialValue);
}
this.currentInitialValue = initialValue;
};
handleInitialValueChange = (value) => {
if (value) {
this.fetchFileDetails(value.split(','));
} else if (!this.isInitialValueEmpty) {
this.resetState();
}
};
fetchFileDetails = (fileIds) => {
fileIds.forEach((id) => {
if (!this.state.uploadedFiles.includes(id)) {
this.queryFileById(id);
}
});
};
queryFileById = (fileId) => {
queryService({ fileId }).then((response) => {
if (response.success && response.data.length > 0) {
const fileInfo = this.convertResponseToFileInfo(response.data[0]);
this.addFileToState(fileInfo);
}
});
};
convertResponseToFileInfo = (data) => ({
name: data.fileName,
uid: data.id,
type: data.fileType,
id: data.id,
url: `/api/files/download?id=${data.id}`
});
addFileToState = (file) => {
const { uploadedFiles, fileRecords } = this.state;
if (!uploadedFiles.includes(file.id)) {
this.setState({
uploadedFiles: [...uploadedFiles, file.id],
fileRecords: [...fileRecords, file]
}, () => this.notifyParent());
}
};
removeFileFromState = (fileToRemove) => {
const { fileRecords } = this.state;
const updatedRecords = fileRecords.filter((file) => file.id !== fileToRemove.id);
this.setState({ fileRecords: updatedRecords }, () => this.notifyParent());
};
resetState = () => {
this.isInitialValueEmpty = true;
this.setState({ uploadedFiles: [], fileRecords: [] }, () => this.notifyParent());
};
notifyParent = () => {
const { onChange } = this.props;
const ids = this.state.uploadedFiles.join(',');
onChange(ids);
};
handleUpload = ({ file }) => {
const formData = new FormData();
formData.append('file', file);
uploadService(formData).then((response) => {
if (response.success && response.data.length > 0) {
const fileInfo = this.convertResponseToFileInfo(response.data[0]);
this.addFileToState(fileInfo);
} else {
message.error('文件上传失败');
}
});
};
render() {
const { fileRecords } = this.state;
const { maxFiles = 1, buttonText = '点击上传' } = this.props;
return (
<Upload
customRequest={(options) => this.handleUpload(options)}
fileList={fileRecords}
onRemove={(file) => this.removeFileFromState(file)}
disabled={maxFiles <= fileRecords.length}
>
<Button>
<span>{buttonText}</span>
</Button>
</Upload>
);
}
}
export default CustomFileUploader;
接下来,在表单中使用该自定义组件:
const TemplateFileItem = ({ data, form, style }) => {
return (
<Form.Item
label="模板文件"
labelCol={{ span: 5 }}
wrapperCol={{ span: 15 }}
style={style}
>
{form.getFieldDecorator('templateFileId', {
rules: [{ required: false, message: '请选择文件' }],
initialValue: data.templateFileId
})(
<CustomFileUploader
maxFiles={1}
placeholder="请选择文件"
autoComplete="off"
/>
)}
</Form.Item>
);
};
上述代码实现了将文件上传组件与表单字段绑定的功能,同时支持初始化值同步和动态更新。
