Bootstrap

Ant Design中组件使用总结-Upload组件

Ant Design中组件使用总结-Upload组件

在使用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 });
  }
;