Ant-design: 上传file.status一直在上传

创建于 2016-07-18  ·  90评论  ·  资料来源: ant-design/ant-design

本地环境

  • antd 版本:1.6.5
  • 操作系统及其版本:mac 10.11.5
  • 浏览器及其版本:50.0.2661.102

你做了什么?

1.6.5版本 Upload控件onChange方法只会执行一次,且info.file.status一直为uploading,http请求正常,返回200。
降级为1.6.4之后正常使用,uploading之后info.file.status为done

你期待的结果是:

实际上的结果:

可重现的在线演示

Question Usage ❓FAQ

最有用的评论

对于受控模式,你应该在 onChange 中始终 setState fileList,保证所有状态同步到 Upload 内。类似这里的写法:http://ant.design/components/upload/#components-upload-demo-fileList

// good

onFileChange(fileList) {
  if ( ... ) {
    ...
  } else {
    ...
  }
  // always setState
  this.setState({ fileList: [...fileList] });
}

...

<Upload fileList={this.state.fileList} onChange={this.onFileChange} />
// bad

onFileChange(fileList) {
  if ( ... ) {
    this.setState({ fileList: [...fileList] });
  } else {
    ...
  }
}

...

<Upload fileList={this.state.fileList} onChange={this.onFileChange} />

建议研习受控组件概念:https://facebook.github.io/react/docs/forms.html#controlled-components


注意需要克隆 fileList 以保障 Upload 能感知数组变化。

- this.setState({ fileList });
+ this.setState({ fileList: [...fileList] });

所有90条评论

我实测是没有问题的,方便给出有问题的完整代码以方便重现么?

对于受控模式,你应该在 onChange 中始终 setState fileList,保证所有状态同步到 Upload 内。类似这里的写法:http://ant.design/components/upload/#components-upload-demo-fileList

// good

onFileChange(fileList) {
  if ( ... ) {
    ...
  } else {
    ...
  }
  // always setState
  this.setState({ fileList: [...fileList] });
}

...

<Upload fileList={this.state.fileList} onChange={this.onFileChange} />
// bad

onFileChange(fileList) {
  if ( ... ) {
    this.setState({ fileList: [...fileList] });
  } else {
    ...
  }
}

...

<Upload fileList={this.state.fileList} onChange={this.onFileChange} />

建议研习受控组件概念:https://facebook.github.io/react/docs/forms.html#controlled-components


注意需要克隆 fileList 以保障 Upload 能感知数组变化。

- this.setState({ fileList });
+ this.setState({ fileList: [...fileList] });

e0a986ed71cd87e506fb8e4ee5e2e0130fc70ae1

我使用Upload控件为什么总是上传失败,总是报错:POST http://localhost:8081/api/nes/2/uploadMusic/r_ty 404 (Not Found)

对于有限制的url怎么去增加身份标识字段和token之类的用action怎么去传?action只给地址,不能加上data么?

在 React.PureComponent 里面还是有问题的 因为React.PureComponent里面做了一层优化判断,filelist有缓存引用, 认为是同一个对象就不会更新, 在React.PureComponent立马 应该生成一个新的对象
handleChange = ({ fileList }) => {
// fixed bug
this.setState({ fileList: fileList.slice() });
}

@afc163

@yongningfu 感谢提示,已更新。

特别提醒一下 : 在使用React shouldComponentUpdate 进行浅比较时,在受控模式当中,即使状态同步到 Upload 内,也不会更新的哦。原因是引用全等===,导致阻止render

上传多张图片,beforeUpload设置上传图片参数限制,onChange获取上传成功的图片列表,上传成功几张图片后,上传一张错误的图片,会将前面上传成功的图片全部清除,请问有什么解决办法吗?

当你回调的时候应该重新设置一下status 比如这样 this.setState( {fileList});

handleChange = (info) => {
console.log(info);

    //把fileList拿出来
    let {fileList} = info;

    const status = info.file.status;
    if (status !== 'uploading') {
        console.log(info.file, info.fileList);
    }
    if (status === 'done') {
        message.success(`${info.file.name} file uploaded successfully.`);
    } else if (status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
    }

    //重新设置state
    this.setState( {fileList});
}

这么说onChange只要是状态有变化,Upload内部就一直在调用,是这样吗

这个问题坑了半天,原来要setState一下。组件不应该设计成这样的,为什么依懒外部状态?

我只想要那个base64码,不跟后台交互,怎么样解决自动向后台发请求的问题哦?

维护这个组件的是个沙雕吧

如果上传失败了,想要显示之前的默认图片,要怎么做呀?

上传失败了,在error处理函数中,call
this.setState({
fileList: intial_list
})
就能显示之前的默认图片

我觉得该组件的上传完成时的回调执行时机可能存在问题,试考虑这样一个情况:

组件关系伪代码:

<Controller>
  <Upload fileList={controller.state.fileList} onUpload={controller.onUpload} />
</Controller>

通过 onUpload 通知父组件 Controller 进行 state 的更新。

但由于 React 的 state 的更新是异步的,在图片上传足够快的情况下,会出现执行顺序为
constroller.onUpload(会调用 controller.setState) -> upload.onSuccess -> upload.componentWillReceiveProps
的情况,导致 upload.onSuccess 执行时 upload 的 state 中没有相应的上传完成的文件。因为 upload 的 state.fileList 更新依赖于 componentWillReceiveProps

因此我觉得该组件目前的受控模式是不可靠的。

可能可行的解决方案:

  1. 在受控模式下,将 onSuccess 等事件的 实际 处理逻辑放到 componentDidUpdate 中进行
  2. 避免将 state.fileList 完全依赖于 props.fileList ,在 组件实例 instance 上维护一份相对独立的 fileList (而非 组件实例的状态 instance.state ),便于处理上传事件

让{file,fileList} = info;
if(file.size / 1024/1024> 10){
返回
}
console.log(file.status)
if(file.status!=“完成”){
fileList = []
}
this.setState({
fileList,
},console.log(
this.state.fileList,
this.props.form.getFieldValue('upload')
))
当我添加

let { file ,fileList } = info;
if(file.size/1024/1024>10){
return
}
console.log(file.status)
if(file.status != "done"){
fileList = []
}
this.setState({
fileList,
},console.log(
this.state.fileList,
this.props.form.getFieldValue('upload')
))
当我添加
if(file.status != "done"){
fileList = []
}
onchange之监听一次,去掉就好了,这是为什么呢

这个问题并没解决吧

componentWillReceiveProps生命周期中调用setState显示图片也并不会发生变化

componentWillReceiveProps = (nextProps) => {
    this.setState(() => ({ 
      fileList: [...nextProps.fileList] 
    }));
  }  
// ...
<Upload FileList={this.state.fileList} ...>
//...

@afc163 upload组件上传多个文件的时候只有一个文件能上传成功是什么情况呢? 通过log看info.fileList里的status都是uploading,percent和response都是undefined,但是http请求是200,求帮助

@PTGuan 当然,这个组件就是一个一个上传的,后端API也是一个一个文件接收的,你需要在upload成功后的callback中递归调用upload,才能批量上传。希望能结局你的问题。

这个问题并没有解决+1

antd 3.8+ 依旧只有status='loading'状态,没有done状态,怎么解决的?

有没有官方正式的解决方案 一直uploading ,但onSuccess 能等到正确的http200响应

问题已经解决了,this.setState({ fileList: [...fileList] }); 这句话很重要,有问题的请重点看这个

@EnixCoda ,我貌似遇到了你描述的问题,我上传偶尔会出现一直显示“正在上传中”。

@withzhaoyu 嗯,其实这里大多数人遇到的都是这个问题。这个组件把上传进度通过 React state 来存储是不太可靠的。

怎么解决啊!!!!!!!!!!一直在uploading

遇坑+1

handleUploaderChange = ({file, fileList}) => {
  console.log('file vo =>', file, fileList);
  if (file.status === 'done') {
    fileList = fileList.map((item, index) => {
      // 相关文件对象数据格式化处理
      return item;
    });
  }
   // 避免原来的文件丢失,这样子写就可以了
  this.setState({ fileList: file.status ? [...fileList] : this.state.fileList });
};

// 上传进度可以通过onProgress中的percent来控制样式,而不是file.status
handleProgress = (event, file) => {
  let {fileList} = this.state;
  fileList = fileList.map(item => {
    if (item.uid === file.uid) {
      item.percent = event.percent;
    }
    return item;
  });
  this.setState({fileList});
};

只要读取文件的base64,不需要和后台交互该怎么办

@pingping92

handleChange = ({ file, fileList }) => {
  const { dispatch, nickname } = this.props;
  const reader = new FileReader();
  reader.onload = e => {
    const base64 = e.target.result;
  };
  reader.readAsDataURL(file.originFileObj);
}
<Upload
  onChange={this.handleAvatarChange}
/>

@AngryPowman ,你可以自己在这个组件基础上再封装一个,功能上还有哪些不能满足的呢

弱弱的在这里问一句,新上传的文件默认不提供url是故意设计的吗?

image

搞笑。现在filelist里面的status还是uploading,就算变成了controlled,我还是把状态为uploading设置上去了。问题根本就没解决

请问下上传文件失败标志是从后端返的->file.response.status,这时候组件没有拦截到,走到了done,文件列表已经展示出来了,我想通过后端返的标志把文件列表清空怎么做?

// 踩了坑 看下源码发现自己使用的问题 如下
// 1.state变量命名
// bad

/*
这里为了方便 使用了与后端返回同样的字段 导致出了问题 这里必须用fileList,不然源码中 this.state.fileList获取是空 就会导致在onSuccess中匹配失败,从而不会在触发第二次onChange事件
*/
state = {imgList:[]} 
<Upload fileList={this.state.imgList} onChange={this.onFileChange} />

// goods

state = {fileList:[]} 
<Upload fileList={this.state.fileList} onChange={this.onFileChange} />

// 2. onFileChange的参数是一个obj(包含file和fileList 两个属性) 而且在onFileChange函数中必须调用 this.setState({ fileList: [...fileList] });

state = {fileList:[]} 
onFileChange({file,fileList}) {
  if ( ... ) {
    ...
  } else {
    ...
  }
  // always setState
  this.setState({ fileList: [...fileList] });
}
<Upload fileList={this.state.fileList} onChange={this.onFileChange} />

有英语吗? 我有这个问题。

@developdeez您的问题是什么? 您正在使用哪个版本的Ant Design?
我以前使用过AntD 3.0,并在此上载组件上工作了几个月。 一切对我来说都很顺利。 我还没有任何问题。 一开始我确实遇到了问题,但最终我将所有问题都解决了。 因此,我有足够的信心来解决所有常见问题。

@swordguard ,蚂蚁3.9.3

问题基本上是无法控制UI的文件列表。 我上传图片并尝试使用按钮清除它,但没有运气。

我也在这里用一些示例代码制作了一张票: https :

你有能力做到这一点吗?

遇坑 +1, 试了this.setState({ fileList: [...fileList] })没用,PureComponent换Component也没差,status只停在uploading除非props里不放fileList,请教各位大大

遇坑 +1, 试了this.setState({ fileList: [...fileList] })没用,PureComponent换Component也没差,status只停在uploading除非props里不放fileList,请教各位大大

可以试试,把fileList定义为字符串呢 ~~==~~
// always setState
this.setState({ fileList: JSON.stringify([info.file]) });

@pingping92

handleChange = ({ file, fileList }) => {
  const { dispatch, nickname } = this.props;
  const reader = new FileReader();
  reader.onload = e => {
    const base64 = e.target.result;
  };
  reader.readAsDataURL(file.originFileObj);
}
<Upload
  onChange={this.handleAvatarChange}
/>

这个问题没有解决啊. file对象里面没有originFileObj这个属性. 这个属性是不是只有在upload后才会出现? 但是现在就是没有打算向后台upload,直接获得base64内容.

this.setState({ fileList: [...fileList] }); 虽然这样能解决客户端展示的问题

但是 按需求,文件上传后,后台返回一个文件id,我在点击提交时,需要把id回传过去
但是状态一直在uploading,没办法拿到后台接口的响应呢
@afc163

这里同样的问题。 在组件Upload ,调用了action属性中的回调,但是UploadFile参数带有空的originFileObjundefined 。 有什么线索如何使用Upload ant组件读取文件内容而不将文件上传到后端吗?

这里同样的问题。 在组件Upload ,调用了action属性中的回调,但是UploadFile参数带有空的originFileObjundefined 。 有什么线索如何使用Upload ant组件读取文件内容而不将文件上传到后端吗?

实际上,您不需要originFileObj,只需使用文件对象即可。 我认为他们已经删除了originFileObj

我在这里是因为我想确保我没有在列表中添加未能成功上传的文件。 换句话说,如果我的file.status === "error"我不想在UI中显示该文件(当然,不想在请求中提交该错误的文件)。 我试图通过使用自己的受控组件并利用fileList来控制它。 我遇到了文件状态从未更改为“上传”的问题。

因此,由于这个问题,我不再使用受控组件。 通过确保normFile仅添加不是“错误”的文件,我能够获得所需的请求。

normFile = (e) => {
    if (Array.isArray(e)) {
      return e.filter(x => x.status !== "error");
    }
    return e && e.fileList.filter(x => x.status !== "error");
  };
const generationRequestDecorator = getFieldDecorator('generationRequest', {
      rules: [
        {
          required: true,
          message: 'Please upload your config'
        }
      ],
      valuePropName: 'fileList',
      getValueFromEvent: this.normFile,
    });
const props = {
      name: 'file',
      action: '/api/to/upload',
      multiple: true,
      onChange(info) {
        if (info.file.status !== 'uploading') {
          console.log(info.file, info.fileList);
        }
        if (info.file.status === 'done') {
          message.success(`${info.file.name} file uploaded successfully`);
        } else if (info.file.status === 'error') {
          message.error(`${info.file.name} file upload failed.`);
        }
      },
    };
const generationRequestArea = generationRequestDecorator(
      <Upload {...props}>
        <Button>
          <Icon type="upload"/> Click to Upload
        </Button>
      </Upload>
    );

再一次,我衷心希望antd团队可以考虑我的建议(以前在这里写过):

维持Upload实例上的文件上传状态,而不是实例的状态。 bc状态并非总是同步更新!

我后面,将后台返回的数据单独渲染在页面,Upload 永远存放最新上传的

@yoonwaiyan
`handleChange =(info)=> {
让fileList = info.fileList;
this.setState({fileList:fileList.slice()});
如果(info.file.status ==='完成'){
message.success(info.file.name +“上传成功”);
fileList = fileList.slice(-1);
fileList = fileList.map((file)=> {
如果(file.response){
file.url = file.response。#检查您的响应并从服务器上选择自己的URL。
}
返回文件;
});

  fileList = fileList.filter((file) => {
    if (file.response) {
      return file.response.#check your respone and choose your own respone status code back from server# === 200;
    }
    return false;
  });

  this.setState({ fileList });
} else if (info.file.status === 'error') {
  message.error(info.file.name + " upload failed");
}

}`

尝试这个。

这个问题,我也遇到了,在一波测试之后,感觉找到了问题所在,解释一下:

handleChange = info => {
    let fileList = info.fileList;
    fileList.filter(file => file.status === 'done');
    this.setState({fileList});
}

测试情况包括:如果直接在handleChange里进行this.setState({fileList})是正常执行的。

我之前的写法都是类似这种,在筛选之后,导致第一次的执行,把fileList筛选成了空数组。所以导致一直只有uploading一种状态。
我觉得问题点在于:在上传后,如果手动把fileList设置为空数组,会影响onChange事件的继续执行,在稍微修改筛选条件之后,确实解决了遇到的问题。

请问下官方维护,是不是这两个属性间有什么绑定关系? @imxiongying

另外官方案例里,有一个这样带筛选的案例(完全控制的上传列表),不知是不是我的网络有问题,这个案例也是有这个情况。

这个问题,我也遇到了,在一波测试之后,感觉找到了问题所在,解释一下:

handleChange = info => {
    let fileList = info.fileList;
    fileList.filter(file => file.status === 'done');
    this.setState({fileList});
}

测试情况包括:如果直接在handleChange里进行this.setState({fileList})是正常执行的。

我之前的写法都是类似这种,在筛选之后,导致第一次的执行,把fileList筛选成了空数组。所以导致一直只有uploading一种状态。
我觉得问题点在于:在上传后,如果手动把fileList设置为空数组,会影响onChange事件的继续执行,在稍微修改筛选条件之后,确实解决了遇到的问题。

请问下官方维护,是不是这两个属性间有什么绑定关系? @imxiongying

另外官方案例里,有一个这样带筛选的案例(完全控制的上传列表),不知是不是我的网络有问题,这个案例也是有这个情况。

受控情况下,在onChange回调里把fileList 设置为空,Upload组件内部的fileList就更新为空数组了,它内部的onSuccess,onProgress等逻辑里会从fileList找触发事件的file,找不到就不触发onChange回调了

@luruozhou 嗯嗯,是这个样子,不知道大家遇到问题的,是不是这个情况,感觉被官方案例误导了

@yidianier handleProgress 请问这个函数在哪里调用的?

@yidianier handleProgress 请问这个函数在哪里调用的?

onProgress={this.handleProgress}

受控组件和纯外部依赖组件各有各的场景使用,受控组件在ant内是有逻辑控制的,比如点击空白取消下拉框等,这些如果都放在外部受控的话,你们又会感觉特别麻烦, 所以受控组件承担一部分基础逻辑,不是组件设计上的问题,不要抱怨了。。。

@all

@afc163

@yidianier handleProgress 请问这个函数在哪里调用的?

onProgress={this.handleProgress}

thanks

在3.13.1也会出现这个问题 @afc163

@xiaolong1024 #14780

还是出现这个问题,跟rc-form有关系吗?

handleUploaderChange = ({file, fileList}) => {
  console.log('file vo =>', file, fileList);
  if (file.status === 'done') {
    fileList = fileList.map((item, index) => {
      // 相关文件对象数据格式化处理
      return item;
    });
  }
   // 避免原来的文件丢失,这样子写就可以了
  this.setState({ fileList: file.status ? [...fileList] : this.state.fileList });
};

// 上传进度可以通过onProgress中的percent来控制样式,而不是file.status
handleProgress = (event, file) => {
  let {fileList} = this.state;
  fileList = fileList.map(item => {
    if (item.uid === file.uid) {
      item.percent = event.percent;
    }
    return item;
  });
  this.setState({fileList});
};

这个答案解决了我的问题!

在3.13.0版本中,打包之后在onChange中操作this.setState({fileList})会导致上传请求被取消,在开发环境中是正常的,还无法确定原因。

@tsuijie 3.13.5 已修复。

请问作者,我上传以后 拿不到fileOBJ下的response 也就拿不到后端返回的fileid 这样怎么处理呢 。我也是同样的情况,status===uploading

`import React,{组件} from'react';
从“ antd”导入{Upload,Icon};
从'@ / utils / utils'导入{urlMapToFileList,fileListTourlMap};
从'@ / services / api'导入{upLoadFile};

类UploadForm扩展了Component {
静态defaultProps = {
hideCheckAll:否,
};

构造函数(道具){
超级(道具);
console.log(urlMapToFileList(props.value));
this.state = {
filesList:urlMapToFileList(props.value)|| urlMapToFileList(props.defaultValue)|| [],
//值:urlMapToFileList(props.value)|| urlMapToFileList(props.defaultValue)|| [],
};
}

onChange =值=> {
const {onChange} = this.props;
如果(onChange){
const selfValue = fileListTourlMap(value);
onChange(selfValue.length?selfValue:null);
}
};
handleChange =(数据)=> {
const {file} =数据;
const {fileList} =数据;
console.log('handleChange',file.status);
if(file.status ==='完成'){
调试器
const {response} = file;
if(response && response.success){
file.url = response.result.url;
fileList.pop();
fileList.push(file);
}
}
if(file.status ==='错误'){
fileList.pop();
}

if(!file.status) {
  fileList = fileList.filter(ele => ele.url)
}
this.setState({filesList: fileList});
this.onChange(fileList);

}

render(){
const {filesList} = this.state;
返回(

accept =“图片/ *”
标头= {{'x-Access-Token':localStorage.getItem('token')}}
action =“ / api / admin / file / upload”
listType =“图片卡”
fileList = {filesList}
onChange = {this.handleChange}
{... this.porps}
>
{filesList.length> = 1吗? 空值:

发布
}


);
}
}

导出默认的UploadForm;
`
这种控制上传数量,但上传状态一直为uploading是啥原因?
@ afc163

虽然都是几年前的老问题了,但是今天也踩了一下坑,说一下自己碰到的坑点,如果你用到了React.PureComponent去创建组件,那么请注意他会默认通过 shouldComponentUpdate 这个生命周期进行浅比较,而你的 filelist 这个 state 引用地址是没有变化的,因此upload组件内部是不会变化的。

let fileList = info.fileList;
/* 这里需要改变一下fileList的引用 */
fileList = JSON.parse(JSON.stringify(fileList));
this.setState({ fileList:fileList});

3.16.1 Upload 还是有问题 change只走一次,建议更新下

需要 this.setState({ fileList: fileList.slice() }) 这样才行

3.16.2 在使用React Hook时,在Upload 的onChange中 fileList 需要进行深拷贝
可以使用 lodash _.cloneDeep(fileList)

集成了 mobx, 在一个 Modal 里用了两个 Upload 组件,并且在相应的 store 里定义了两个 fileList, 其中一个Upload 的 onChange 事件走的是正常的上传流程(uploading 和 done 状态都接收到了),但是另一个比较失望,一直只有 uploading,最终只能使用这种方式解决
修改前: this.fileList[0] = file; 修改后: this.fileList = []; this.fileList.push(file);
并且,如果 this.fileList 来自于继承的 class, 用修改后的这种方式也不行

if (status === 'error') {
    message.success(`${file.name} upload failed.`);
    const fileList = this.state.fileList.filter(file => !file.error);
    this.setState({
        fileList
    }, () => {
        console.log(this.state.fileList)
    })
}

在失败的时候我想移除失败的显示项, 通过这种方法为什么state没有改变呢?

console.log是正确的,state已经是空的了, 但是开发者工具还是有,并且上传失败的图片也显示出来了

https://github.com/ant-design/ant-design/issues/2423#issuecomment -491143417

this.setState({
    fileList:[...fileList]
}

对于有限制的url怎么去增加身份标识字段和token之类的用action怎么去传?action只给地址,不能加上data么?

可以放到Header里边

用这个技巧解决了我的问题
Screen Shot 1398-03-25 at 6 29 26

我有动态输入创建系统,因此有了新的动态道具,您就可以告诉antd有关传入的道具

当我开始使用React.Component而不是React.PureComponent时,它固定为我。

当我使用modal.info和控件文件列表时,onChange仅被调用一次。 但是当我删除Modal时,它可以工作

可以

1: 使用React.Component
2: 注意检查getDerivedStateFromProps里面是否设置了fileList,是否设置正确。
3: fileList: this.state.fileList
4: onChange: ({file, fileList}) => {
this.setState({fileList});
}

3.19.7还有这个问题

我发布了一个成功的案例供您参考。 我以前有这个问题。 这里也算一下做笔记,以方便自己以后忘记方便的搜索

环境:

  • antd: 4.0.0-rc.1
  • 专业版: 5.0.0
  • 反应: 16.9.17
import React, { useState } from 'react';
import { Modal, Upload, Button, message } from 'antd';
import { UploadOutlined } from '@ant-design/icons/lib';
import { UploadProps } from 'antd/lib/upload';
import { deleteArtifact } from '@/services/artifact';

interface UploadModalType {
  visible: boolean
  onCancel: () => void
  projectId: number
}

const UploadModal: React.FC<UploadModalType> = props => {
  const { visible, onCancel, projectId } = props;
  const [fileList, setFileList] = useState();

  const uploadProps: UploadProps = {
    name: 'file',
    fileList,
    listType: 'text',
    action: 'http://localhost:8080/v1/artifacts',
    data: { project_id: projectId, type: 'application/json' },
    onChange(info) {

      setFileList(info.fileList.slice()); // Note: A new object must be used here!!!

      if (info.file.status === 'done') {
        message.success(`${info.file.name} file uploaded successfully`);
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
    onRemove(file) {
      const promise: PromiseLike<void | boolean> = deleteArtifact({ filename: file.response });
      promise.then((value: any) => {
        if (value === '' || value instanceof Response && value.status === 205) {
          const index = fileList.indexOf(file);
          const newFileList = fileList.slice();
          newFileList.splice(index, 1);
          setFileList(newFileList);
        }
      });
    },
  };

  return (
    <Modal
      destroyOnClose
      title='上传归档文件'
      visible={visible}
      onCancel={onCancel}
    >
      <Upload
        {...uploadProps}
      >
        <Button>
          <UploadOutlined/> Click to Upload
        </Button>
      </Upload>
    </Modal>
  );
};

export default UploadModal;

好坑啊,uploading状态必须设置fileList不然,只执行一次,折腾半天,无语死了。

我发布了一个成功的案例供您参考。 我以前有这个问题。 这里也算一下做笔记,以方便自己以后忘记方便的搜索

环境:

  • antd: 4.0.0-rc.1
  • 专业版: 5.0.0
  • 反应: 16.9.17
import React, { useState } from 'react';
import { Modal, Upload, Button, message } from 'antd';
import { UploadOutlined } from '@ant-design/icons/lib';
import { UploadProps } from 'antd/lib/upload';
import { deleteArtifact } from '@/services/artifact';

interface UploadModalType {
  visible: boolean
  onCancel: () => void
  projectId: number
}

const UploadModal: React.FC<UploadModalType> = props => {
  const { visible, onCancel, projectId } = props;
  const [fileList, setFileList] = useState();

  const uploadProps: UploadProps = {
    name: 'file',
    fileList,
    listType: 'text',
    action: 'http://localhost:8080/v1/artifacts',
    data: { project_id: projectId, type: 'application/json' },
    onChange(info) {

      setFileList(info.fileList.slice()); // Note: A new object must be used here!!!

      if (info.file.status === 'done') {
        message.success(`${info.file.name} file uploaded successfully`);
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} file upload failed.`);
      }
    },
    onRemove(file) {
      const promise: PromiseLike<void | boolean> = deleteArtifact({ filename: file.response });
      promise.then((value: any) => {
        if (value === '' || value instanceof Response && value.status === 205) {
          const index = fileList.indexOf(file);
          const newFileList = fileList.slice();
          newFileList.splice(index, 1);
          setFileList(newFileList);
        }
      });
    },
  };

  return (
    <Modal
      destroyOnClose
      title='上传归档文件'
      visible={visible}
      onCancel={onCancel}
    >
      <Upload
        {...uploadProps}
      >
        <Button>
          <UploadOutlined/> Click to Upload
        </Button>
      </Upload>
    </Modal>
  );
};

export default UploadModal;

我在使用Func组件时遇到同样的问题。 Info.status始终具有上载状态,并且onChange调用仅一次

@tsuijie 3.13.5 已修复。

3.13.5 我也出现了同样的问题 onChange中操作this.setState({fileList})会导致上传请求被取消

如果没有使用其action接口,在上传后会出现一直上传中的状态,需要手动将每个文件的status设置为done

如果没有使用其action接口,在上传后会出现一直上传中的状态,需要手动将每个文件的status设置为done

请检查fileList回写state时有没有使用新对象,[...fileList]

好的  谢谢

---Original---
From: "Amumu"<[email protected]>
Date: Sun, Jul 26, 2020 17:59 PM
To: "ant-design/ant-design"<[email protected]>;
Cc: "Comment"<[email protected]>;"SCLGIS"<[email protected]>;
Subject: Re: [ant-design/ant-design] Upload file.status is always being uploading (#2423)

如果没有使用其action接口,在上传后会出现一直上传中的状态,需要手动将每个文件的status设置为done

请检查fileList回写state时有没有使用新对象,[...fileList]


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

如果我使用启用了“ multiples”选项的钩子,它将不起作用。
如果选择3个文件,则列表中将显示2个文件。 如果选择5个文件,则只有3个,有时只有4个。如果删除prop“ fileList”,它可以正常工作,并且可以看到列表中的所有文件,但是我无法控制它们-我需要使用“ fileList”道具。
如果我使用类组件而不是钩子useState,则会有不同的行为。

在4.5.1上也遇到这个问题,一直是uploading的状态。试了前面大佬说的方法都没用,最后看了源码发现是因为我render时每次的upload组件的key值不一样,导致重新渲染了,源码默认就取消了前面的上传请求,导致一直是uploding的状态,key值固定然后就正常可以上传成功了

@tsuijie 3.13.5 已修复。

3.13.5 我也出现了同样的问题 onChange中操作this.setState({fileList})会导致上传请求被取消

此页面是否有帮助?
0 / 5 - 0 等级