在使用Ant Design的Upload组件中,遇到一些问题,简单的分享一下
一.在编辑页面,Upload的图片列表的初始化问题
在使用Upload组件在新建页面的时候所有的图片都是通过Upload组件上传的,因此在管理起来也比较容易,Upload组件引用如下:
{getFieldDecorator('wechatUrl')(
<Upload
className={styles.uploadInline}
name="files"
action="/hyapi/resource/image/upload"
onChange={this.handleChange}
fileList={this.state.fileList}
beforeUpload={this.handleBeforeUpload}
>
<Button>
<Icon type="upload" />上传图片
</Button>
</Upload>
)}
但是当在处理编辑页面的时候,需要从数据库中读取已经上传的文件,因为Upload的图片列表都存储在this.state.fileList当中,因此后台的数据读取到图片之后将图片路径构建到fileList数组的url中,就会在Upload组件显示。如下代码所示。
componentDidMount() {
const { dispatch } = this.props;
this.props.dispatch({
type: 'selfinfo/fetchSelfInfo',
callback: () => {
if(this.props.infoObj.wechatUrl) {
this.setState({
fileList: [{
uid: -1,
name: '微信二维码',
status: 'done',
url: this.props.infoObj.wechatUrl,
}],
});
}
},
});
}
现在遇到的问题就是,编辑页面,首次进入Upload组件上的图片都不是通过组件上传图片操作上传的,若在该次提交表单数据的时候,不进行图片的上传更改,而是改变别的数据之后提交表单,是不能通过values.wechatUrl获取图片列表的,只有通过Upload组件新上传一张图片之后,才可以通过values获取之前默认的后台传过来的已经上传的图片列表,但是this.state.fileList里面的数据一直是和图片列表保持一致的,因此编辑页面在向后台传递数据的时候,需要从this.state.fileList取出在传递给后台。
二.Upload的beforeUpload函数验证文件类型的时候,返回false
当需要对上传文件进行限制的时候,一般调用beforeUpload函数来进行验证,当上传的文件不是图片的时候,beforeUpload返回false。
handleBeforeUpload = (file) => {
//限制图片 格式、size、分辨率
const isJPG = file.type === 'image/jpeg';
const isJPEG = file.type === 'image/jpeg';
const isGIF = file.type === 'image/gif';
const isPNG = file.type === 'image/png';
if (!(isJPG || isJPEG || isGIF || isPNG)) {
message.error("上传图片的格式不正确,不是JPG、JPEG、GIF、PNG");
return false;
}
return true;
}
这时候发现会将之前的正确的上传清除,并且图片列表也会包含这个错误的记录,在onChange函数中打印调用情况的时候发现,beforeUpload如果返回false会触发一次额外的onChange调用。并传入onChange当前的这张图片不包含之前的图片。就会在上传图片列表显示这次不符合验证的上传记录。
并且在控制台会打印输出一次onChange调用,可以看见传进来fileList的参数只有这一次上传的txt没有之前上传其他记录。
解决办法是在beforeUpload验证中,返回一个Promise对象这样就不会在触发额外的onChange了。并且显示上传成功的列表也不回包含该记录。
handleBeforeUpload = (file) => {
//限制图片 格式、size、分辨率
const isJPG = file.type === 'image/jpeg';
const isJPEG = file.type === 'image/jpeg';
const isGIF = file.type === 'image/gif';
const isPNG = file.type === 'image/png';
if (!(isJPG || isJPEG || isGIF || isPNG)) {
message.error("上传图片的格式不正确,不是JPG、JPEG、GIF、PNG");
}
return new Promise((resolve, reject) => {
if (!(isJPG || isJPEG || isGIF || isPNG)) {
reject(file);
} else {
resolve(file);
}
});
}
三.Upload的file的status状态为error的时候,上传失败的图片还显示在已上传列表
当后台接口不存在,或者上传失败的时候图片的状态码为errror的时候,发现出现图片仍出现在上传列表,并且percent为100,但是loading一直为true的情况。
可以在控制台打印一些图片的状态,包括status,percent。
handleChange = (info) => {
console.log(info);
console.log("info");
console.log("status : " + info.fileList[0].status);
console.log("percent : " + info.fileList[0].percent);
let fileList = info.fileList;
fileList = fileList.slice(-1);
}
打印的结果如下,可以看见status从uploading 到 error,percent从0到100,最后这条error记录也被记录在了fileList中,因此会出现上面的现象,现在需要在onChange里面手动过滤掉上传状态为error的图片。(发现一个神奇的问题 打印的info里面的fileList里面的数据每次都显示是最后的结果,但打印info.fileList[0].status确实从一开始到最后变化的数据,不知道为什么两次打印数据不一致??)
在onChange中修改代码如下,将过滤掉status为error的图片,不再显示
handleChange = (info) => {
let fileList = info.fileList;
fileList = fileList.slice(-1);
//1. filter status is not error
fileList = fileList.filter((file) => {
if (file.status === 'error') {
return false;
}
return true;
});
// 2. read from response and show file link
fileList = fileList.map((file) => {
if (file.response) {
file.url = file.response.obj[0];
}
return file;
});
// 3. filter successfully uploaded files according to response from server
fileList = fileList.filter((file) => {
if (file.response) {
return file.response.success === true;
}
return true;
});
this.setState({ fileList });
}