提交 42708fe4 编写于 作者: A afc163

Refractor upload API

1. Remove limit urlResolver and onRemove
2. Remove onSuccess onProgress onError
3. Add onChange
4. Add fileList and defaultFileList props
上级 f50342b2
......@@ -12,8 +12,10 @@ var Upload = antd.Upload;
var props = {
action: '/upload.do',
onChange(info) {
console.log(info.file);
console.log(info.fileList);
if (info.file.status !== 'uploading') {
console.log(info.file);
console.log(info.fileList);
}
}
};
......@@ -22,7 +24,6 @@ React.render(
<button className="ant-btn ant-btn-ghost">
<i className="anticon anticon-upload"></i> 点击上传
</button>
</Upload>,
document.getElementById('components-upload-demo-basic')
);
</Upload>
, document.getElementById('components-upload-demo-basic'));
````
# 传入已上传的文件
- order: 1
对已上传的文件进行编辑。
---
````jsx
var Upload = antd.Upload;
var props = {
action: '/upload.do',
onChange(info) {
if (info.file.status !== 'uploading') {
console.log(info.file);
console.log(info.fileList);
}
},
defaultFileList: [{
uid: 12345,
name: 'xxx.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png'
}, {
uid: 12346,
name: 'yyy.png',
status: 'done',
url: 'http://www.baidu.com/yyy.png'
}]
};
React.render(
<Upload {...props}>
<button className="ant-btn ant-btn-ghost">
<i className="anticon anticon-upload"></i> 点击上传
</button>
</Upload>
, document.getElementById('components-upload-demo-defaultfilelist'));
````
# 拖拽上传
- order: 3
- order: 4
样式简单一些。
......
# 拖拽上传
- order: 2
- order: 3
可以把文件拖入指定区域,完成上传,同样支持点击上传。
......
# 完全控制的上传列表
- order: 2
使用 `fileList` 对列表进行完全控制,可以实现各种自定义功能,以下演示三种情况:
1) 上传列表数量的限制。
2) 读取远程路径并显示链接。
3) 按照服务器返回信息筛选成功上传的文件。
---
````jsx
var Upload = antd.Upload;
var fileList = [{
uid: 123,
name: 'xxx.png',
status: 'done',
url: 'http://www.baidu.com/xxx.png'
}];
var MyUpload = React.createClass({
getInitialState() {
return {
fileList: fileList
};
},
handleChange(info) {
let fileList = info.fileList;
// 1. 上传列表数量的限制
// 只显示最近上传的一个,旧的会被新的顶掉
fileList = fileList.slice(-1);
// 2. 读取远程路径并显示链接
fileList = fileList.map(function(file) {
if (file.response) {
// 组件会将 file.url 作为链接进行展示
file.url = JSON.parse(file.response).url;
}
return file;
});
// 3. 按照服务器返回信息筛选成功上传的文件
fileList = fileList.filter(function(file) {
if (file.response) {
return JSON.parse(file.response).status === 'success';
}
return true;
});
this.setState({
fileList: fileList
});
},
render() {
var props = {
action: '/upload.do',
onChange: this.handleChange
};
return <Upload {...props} fileList={this.state.fileList}>
<button className="ant-btn ant-btn-ghost">
<i className="anticon anticon-upload"></i> 点击上传
</button>
</Upload>;
}
});
React.render(<MyUpload />, document.getElementById('components-upload-demo-filelist'));
````
# 文件列表限制
- order: 1
`limit` 属性控制文件列表数的上限。如设为 1 时,表示只能上传一个文件,新文件会顶掉旧文件。
---
````jsx
var Upload = antd.Upload;
var props = {
action: '/upload.do',
limit: 1,
onStart(file) {
console.log(file.uid);
}
};
React.render(
<Upload {...props}>
<button className="ant-btn ant-btn-ghost">
<i className="anticon anticon-upload"></i> 点击上传,只支持一个文件
</button>
</Upload>,
document.getElementById('components-upload-demo-limit')
);
````
......@@ -2,7 +2,7 @@ export default function getFileItem(file, fileList) {
let matchWay = (!file.uid) ? 'byName' : 'byUid';
let target = fileList.filter((item) => {
if (matchWay === 'byName') {
return item.filename === file.filename;
return item.name === file.name;
} else {
return item.uid === file.uid;
}
......
......@@ -12,76 +12,73 @@ function noop() {
const AntUpload = React.createClass({
getInitialState() {
return {
fileList: []
fileList: this.props.fileList || this.props.defaultFileList || []
};
},
onStart(file) {
let nextFileList = this.state.fileList;
file.status = 'started';
file.status = 'uploading';
nextFileList.push(file);
if (nextFileList.length === this.props.limit + 1) {
nextFileList = nextFileList.slice(1);
}
this.setState({
fileList: nextFileList
});
this.props.onChange({
file: file,
fileList: nextFileList
});
},
removeFile(file){
var fileList = this.state.fileList.concat();
removeFile(file) {
file.status = 'removed';
let fileList = this.state.fileList.concat();
let targetItem = getFileItem(file, fileList);
var index = fileList.indexOf(targetItem);
let index = fileList.indexOf(targetItem);
if (index !== -1) {
fileList.splice(index, 1);
}
this.setState({
fileList: fileList
});
return fileList;
},
onSuccess(ret, file) {
var fileList = this.state.fileList.concat();
Message.success(file.name + '上传完成');
onSuccess(response, file) {
let fileList = this.state.fileList.concat();
Message.success(file.name + '上传完成');
let targetItem = getFileItem(file, fileList);
targetItem.status = 'done';
targetItem.response = response;
// 解析出文件上传后的远程地址
if (typeof this.props.urlResolver === 'function') {
targetItem.url = this.props.urlResolver(ret);
targetItem.url = this.props.urlResolver(response);
}
this.setState({
fileList: fileList
});
this.props.onChange({
this.onChange({
file: targetItem,
fileList: this.state.fileList,
response: ret
fileList: this.state.fileList
});
},
onProgress(e, file) {
this.props.onChange({
this.onChange({
event: e,
file: file,
fileList: this.state.fileList
});
},
onError(err, response, file) {
Message.error(file.name + ' 上传失败');
this.removeFile(file);
onError(error, response, file) {
Message.error(file.name + ' 上传失败');
file.error = error;
file.response = response;
this.props.onChange({
error: err,
file: file,
fileList: this.fileList
});
this.handleRemove(file);
},
onRemove(file) {
this.props.onChange({
handleRemove(file) {
let fileList = this.removeFile(file);
this.onChange({
file: file,
fileList: this.fileList
fileList: fileList
});
},
onChange(info) {
// 1. 有设置外部属性时不改变 fileList
// 2. 上传中状态(info.event)不改变 fileList
if (!('fileList' in this.props) && !info.event) {
this.setState({
fileList: info.fileList
});
}
this.props.onChange(info);
},
getDefaultProps() {
return {
type: 'select',
......@@ -91,14 +88,20 @@ const AntUpload = React.createClass({
data: {},
accept: '',
onChange: noop,
limit: Number.MAX_VALUE,
urlResolver: function(ret) {
urlResolver: function(response) {
try {
return JSON.parse(ret).url;
return JSON.parse(response).url;
} catch(e) {}
}
};
},
componentWillReceiveProps(nextProps) {
if ('fileList' in nextProps) {
this.setState({
fileList: nextProps.fileList
});
}
},
render() {
let type = this.props.type || 'select';
let props = assign({}, this.props, {
......@@ -126,7 +129,7 @@ const AntUpload = React.createClass({
</Upload>
</div>
<UploadList items={this.state.fileList}
limit={props.limit} />
onRemove={this.handleRemove} />
</div>
);
}
......
......@@ -18,30 +18,41 @@
## API
| 参数 | 说明 | 类型 | 默认值 |
|----------- |--------------------------------------------------------- | ---------- |-------|
| name | 可选参数, 上传的文件 | String | file |
| 参数 | 说明 | 类型 | 默认值|
|------------|--------------------------------------------------------------| ----------- |-------|
| name | 可选参数, 上传的文件 | String | file |
| action | 必选参数, 上传的地址 | String | 无 |
| data | 可选参数, 上传所需参数 | Object | 无 |
| multiple | 可选参数, 是否支持多选文件,支持ie10+ | Boolean | false |
| accept | 可选参数, 接受上传的文件类型, 详见input accept Attribute | String | 无 |
| onError | 可选参数, error callback |Function | 无 |
| onSuccess | 可选参数, success callback | Function | 无 |
| onProgress | 可选参数, progress callback, 现代浏览器有效 | Function | 无 |
| urlResolver| 通过解析请求返回数据,获得文件上传的远程地址 | Function | `function() { return JSON.parse(ret).url }` |
| limit | 文件上传数量的限制 | Number | Number.MAX_VALUE |
| multiple | 可选参数, 是否支持多选文件,支持 `ie10+` | Boolean | false |
| accept | 可选参数, 接受上传的文件类型, 详见 input accept Attribute | String | 无 |
| onChange | 可选参数, 上传文件改变时的状态,详见 onChange | Function | 无 |
### onError
### onChange
错误回调,有三个参数返回
文件状态改变的回调,返回为
1. `err` 请求返回错误信息
2. `responce` 请求响应,包括错误状态码等信息
3. `file` 错误的文件对象
```js
{
file: { ... },
fileList: [ ... ],
event: { ... }
}
```
### onSuccess
1. `file` 当前操作的文件对象。
成功回调,返回两个参数
```js
{
uid: 'uid', // 文件唯一标识
name: 'xx.png' // 文件名
status: 'done', // 状态:uploading done removed
response: '{"status":"success"}' // 服务端响应内容
}
```
1. `result` 上传图片返回结果
2. `file` 文件对象
2. `fileList` 当前的文件列表。
3. `event` 上传中的服务端响应内容,包含了上传进度等信息,高级浏览器支持。
## 显示下载链接
默认会解析服务器返回数据的 `body.url` 作为下载链接,需要自行配置请使用 fileList 属性进行展示控制。
......@@ -22,21 +22,15 @@ export default React.createClass({
}
},
handleClose(file) {
let items = this.state.items;
let removeItem = getFileItem(file, items);
if (removeItem) {
items.splice(items.indexOf(removeItem), 1);
}
this.setState({
items: items
});
this.props.onRemove(file.file);
this.props.onRemove(file);
},
render() {
let list = this.state.items.map((file) => {
let statusIcon = file.status === 'done' ? <i className={'anticon anticon-check ' + prefixCls + '-success-icon'}></i> :
let statusIcon = file.status === 'done' ?
<i className={'anticon anticon-check ' + prefixCls + '-success-icon'}></i> :
<i className="anticon anticon-loading"></i>;
let filename = file.url ? <a className={prefixCls + '-item-name'} href={file.url} _target="_blank">{file.name}</a> :
let filename = file.url ?
<a className={prefixCls + '-item-name'} href={file.url} _target="_blank">{file.name}</a> :
<b className={prefixCls + '-item-name'}>{file.name}</b>;
return (
<div className={prefixCls + '-list-item'} key={file.uid}>
......@@ -47,10 +41,10 @@ export default React.createClass({
</div>
);
});
return (<div className={prefixCls + '-list'}>
return <div className={prefixCls + '-list'}>
<Animate transitionName={prefixCls + '-margin-top'}>
{list}
</Animate>
</div>);
</div>;
}
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册