Form+Upload实现文件上传全步骤
11/21/2025, 12:10:56 PM
#React#upload#历史文章迁移
以图片上传为例,借助antd中Form组件和Upload来实现一下上传。
参考官方文档示例:https://ant.design/components/form-cn/#components-form-demo-validate-other
一、组件的引用:
<Form onSubmit={this.handleSubmit.bind(this)}>
<Form.Item>
{getFieldDecorator('file', {
valuePropName: 'fileList',
getValueFromEvent: this.normFile,
initialValue: this.state.fileList || [],
})(
<Upload {...props}>
<Button className='upload-btn'>
<Icon type="upload" /> 点击上传
</Button>
</Upload>,
)
}
</Form.Item>
</Form>
initialValue是加载默认的文件列表,valuePropName如果没有的话,在listType:'picture'的设置下,图片缩略图会显示不出来。不过这样设置会报一个错:
不影响实际使用,若有要求的可以自己优化一下valuePropName或图片缩略显示等。
二、上传配置:
const props = {
// 图片的删除,可以加入axios请求配合后台接口
onRemove: (file) => {
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
},
// 上传前的验证,可以在这里设置文件类型,比如只能上传图片,return false表示手动上传,非自动提交
beforeUpload: (file) => {
let type1 = "image/jpeg";
let type2 = "image/png";
const isPicture = file.type === type1 || file.type === type2;
if(isPicture === false){
message.error("文件类型错误,请重新选择!");
}
else{
this.setState(state => ({
fileList: [...state.fileList, file],
}));
}
},
// 文件列表
fileList,
// 展示类型
listType: 'picture',
};
还有上传前的处理比如添加水印,可以自行参考官方文档。
三、文件处理:
在组件使用的时候应该还会注意到一个事件this.normFile,这个可以处理文件列表的展示,比如不符合图片类型的文件就不让它添加到列表里面展示了。
normFile = e => {
let type1 = "image/jpeg";
let type2 = "image/png";
const isPicture = e.file.type === type1 || e.file.type === type2;
if(isPicture === false){
e.fileList.pop();
}
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
};
不符合类型的建议删掉,避免上传。
四、文件上传:
完成上面的操作后,就是调用handleSubmit函数来上传了:
handleSubmit (e) {
// 文件信息
let { fileList } = this.state;
let formData = new FormData();
// 批量上传
for (let item of fileList) {
formData.append('file', item)
}
axios.post(url,formData,{
'Content-Type':'multipart/form-data'
}).then(res=>{
...
})
}
至此,关键的上传就完成了。
五、默认文件:
当我们进行修改时,一般有图片的话就会有默认文件展示,实现方法如下:
// 默认文件
let reportFile = this.props.rowRecord.reportFile;
if(reportFile !== undefined){
reportFile.map((val,ind)=>{
val.uid = -ind;
})
// 方法一,设置fileList,通过initialValue来加载默认值
this.setState({
fileList: reportFile
})
// 方法二,直接设置值
this.props.form.setFieldsValue({ file: reportFile
});
}
这两种方法都能设置,第一种不行换第二种。
六、文件删除:
最后就是文件的删除了,这主要取决于上传方式,如果是自动上传,那么只要在我说的onRemove里面加入异步请求就行了,但是如果是随表单统一提交,那样的方式就不友好,毕竟用户也有后悔的权利。处理方式如下:
onRemove: (file) => {
let deleteFileArr = this.state.deleteFileArr;
if(file.id !== undefined){
deleteFileArr.push(file.id);
}
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
deleteFileArr,
fileList: newFileList,
};
});
},
对比之前的onRemove可以发现,加入了一个自定义的deleteFileArr来存储要删除的文件id,只有提交时,才会统一传到后台处理。如果用户后悔了,那么就直接退出页面就能清空取消了。提交时把要删除的文件id传到后台,进行批量删除,就可以了。