React文件上传控件

最近做项目需要使用上传文件的React控件,于是使用了开源的Upload控件:
https://github.com/react-component/upload 并稍加改造实现了一个更灵活的FileUpload类。
顺便提一下:https://github.com/react-component 是基于antd的一套react控件的实现。

在项目中引入,核心代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { Upload, Button, Icon } from 'antd';
......
class Demo extends Component{
render= () => {
let uploadProps = {
name: 'file',
beforeUpload: (file)=> {
this.setState({
file: file
});
return false;
}
};
<Upload {...uploadProps}>
<Button>
<Icon type="upload"/>选择文件
</Button>
</Upload>
}
}

Upload控件默认在选择文件之后,会直接上传。按照我的项目需求,应该是有
一个提交按钮来触发上传行为。这里beforeUpload拿到file对象之后,直接返
回了false,就可以终止Upload控件的默认上传行为。

控制上传时机

以下代码是上传文件所需的参数,其中endpoint是后端接口url。data是除了
文件对象之外的其他参数。filename是文件对象在post请求里的key。file则
是上面代码中拿到的文件对象。onProgress可以监听上传进度,具体实现请继
续往下看。onError和onSuccess想必都知道了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const option = {
endpoint: 'http://www.example.com/fileupload',
data: {
name: this.state.file.name,
... //
},
filename: 'file',
file: this.state.file,
onProgress: (e) => {
//e.percent就是进度的百分比
},
onError: (e) => {
},
onSuccess: (xhr) => {
this.createPackageHandler(xhr, manifest);
}
};

基于XMLHttpRequest实现最简单的上传功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
export default function UploadFile(option) {
const xhr = new XMLHttpRequest();
if(option.onProgress && xhr.upload) {
xhr.upload.onprogress = function progress(e) {
if(e.total > 0) {
e.percent = e.loaded / e.total * 100;
}
option.onProgress(e);
};
}
const commonFormData = new FormData();
if(option.data) {
Object.keys(option.data).map(key => {
commonFormData.append(key, option.data[key]);
});
}
commonFormData.append(option.filename, option.file);
xhr.onload = () => {
if(xhr.status < 200 || xhr.status >=300) {
return option.onError(xhr);
}
option.onSuccess(xhr);
};
xhr.onerror = (e) => {
option.onError(e);
};
xhr.open("post", option.endpoint,true);
if (option.withCredentials && 'withCredentials' in xhr) {
xhr.withCredentials = true;
}
const headers = option.headers || {};
for (const h in headers) {
if (headers.hasOwnProperty(h) && headers[h] !== null) {
xhr.setRequestHeader(h, headers[h]);
}
}
xhr.send(commonFormData);
//这里返回abort函数,可以让用户掌握abort的控制权
return {
abort: ()=>{
xhr.abort();
}
}
}

使用UploadFile类就可以在想要上传的时候进行上传操作了,而且将xhr对象
直接返回给onSuccess函数,这样用户可以利用xhr获取Response里的header
或者body。纯粹的原生JavaScript实现前端上传功能,至于后端的接口怎么实
现,等待下一篇。