react class类组件+fetch实现批量上传的功能
- 批量上传在现阶段的工作中一共是有两中实现防范
- 批量多个上传文件的时候是请求一次接口,然后将所以的formate全部传给后端
- 是循环拿到批量上传的files,然后前端循环这个files,每一次都需要调用一次后端的接口(本次使用的方式也是这种)
import React, { Component } from 'react';
import { Button, Icon, Toaster } from 'UI';
import URL from './url';
import './index.scss';
export default class UploadBtn extends Component {
constructor(props) {
super(...props);
this.state = {
data: [],
loading: false,
}
}
componentDidMount() {
const { data } = this.props;
if (!data) {
this.setState({ data: [] });
} else {
this.setState({ data });
}
}
componentWillReceiveProps(props) {
const { data } = props;
if (!data) {
this.setState({ data: [] });
} else {
this.setState({ data: data });
}
}
// 上传附件格式限制校验
validateLimitFormat() {
}
validateLimitSize() {
}
// 上传成功后把数据放到data
handleImport = (...arg) => {
const { action, multiple, limit } = arg;
// console.log(action, multiple, limit)
const input = document.createElement('input');
input.type = 'file';
input.id = 'handle-import';
input.multiple = true;
input.click();
// console.log(input);
// 大小的限制
// 格式的限制
// 批量上传-请求多个接口
input.addEventListener('change', e => {
let files = e.target.files;
// console.log(e.target.files);
let classFiles = Array.prototype.slice.call(files)
classFiles.forEach((file, index) => {
const formData = new FormData();
formData.append('file', file);
try {
this.setState({ loading: true });
fetch(URL.UPLOAD, {
method: 'POST',
body: formData,
credentials: "same-origin"
})
.then(res => {
return res.json();
})
.then(data => {
// console.log(data)
if (data.status === 0) {
Toaster.show({
type: 'error',
title: (error.data && data.data.message) || '上传失败!',
});
} else {
let imgData = this.state.data;
imgData.push(data.data);
this.setState({
data: imgData,
});
}
this.setState({ loading: false });
input.remove();
}).catch(error => {
console.log(error)
Toaster.show({
type: 'error',
title: (error.data && error.data.message) || '上传失败!',
duration: 8
});
this.setState({ loading: false });
throw error;
});
} catch (error) {
console.log(error)
this.setState({ loading: false });
throw error;
} finally {
}
})
});
};
// 删除
deleteFile(e, index, fileId) {
let data = this.state.data;
data.splice(index, 1);
this.setState({ data });
}
// 暴露出去的钩子
getValue() {
return this.state.data || [];
}
render () {
const { data=[], loading } = this.state;
const {
mode="edit",
type="button",
disabled = false,
shape="",
icon="plus",
btnType="primary",
size="",
text="上传",
className="",
action=URL.UPLOAD,
multiple=false,
limit=[],
maxLength = 50,
showBtn,
} = this.props;
return (
<div className={`${className} c-upload-btn file-upload-type-${type}`}>
<div className={`file-upload-type-${type}`}>
{ (data.length < maxLength) &&
<Button
disabled={disabled}
loading={loading}
onClick={this.handleImport.bind(this, action, multiple, limit)}
shape={shape}
icon={icon}
type={btnType}
size={size}
>{text}</Button>
}
<div>
{
validateArray(data) && data.map((item, index) =>
<a key={index} className="upload-file-list" href="javascript:void(0)">
<span className="upload-file-list-name">
<span>{item.fileName}</span>
</span>
<span className="upload-file-list-close" onClick={e => this.deleteFile(e, index, item.fileId)}>
<Icon className="close-icon" type="cross" />
</span>
<span className="upload-file-list-download" onClick={()=>{
downLoad(URL.GRT_URL, item.fileId)
}}>
<Icon className="download-icon" type="export" />
</span>
<span className="upload-file-list-preview" onClick={()=>{
visibilityFile(URL.PREVIEW, item)
}}>
<Icon className="preview-icon" type="eye" />
</span>
</a>
)
}
</div>
</div>
</div>
)
}
}
// 备注:新的upload组件,支持批量上传功能, 支持下载和预览
// 逐步替换掉现有的老的组件
// 接受参数
// type="button" // 附件类型
// disabled = false,
// shape="",
// icon="plus",
// btnType="primary",
// size="",
// text="上传",
// className="",
// action,
// multiple,
// limit
// maxLength // 上传最大数
附上css
$success-color: #118bfb;
$error-color: red;
.c-upload-btn{
// button 的upload组件
.file-upload-type-button{
.upload-file-list{
font-size: 14px;
display: block;
margin:10px 10px 10px 0px;
color: #333;
padding: 5px;
background: rgb(244,244,244);
&-name{
display: inline-block;
color: rgba(0,0,0,0.87);
width: -moz-calc(100% - 125px);
width: -webkit-calc(100% - 125px);
width: calc(100% - 125px);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.report-icon{
margin: 0 5px 0 5px;
}
&:hover {
color: $success-color;
}
}
&-close, &-download, &-preview{
color: rgba(0,0,0,0.87);
float: right;
padding: 2px 5px;
margin: 0 5px 0 0px;
cursor: pointer;
&:hover{
color: $success-color;
}
.download-text, .preview-text{
position: relative;
top: -1px;
left: 5px;
}
}
// .success-text, .error-text{
// float: right;
// margin-right: 40px;
// .success-icon, .error-icon{
// margin-right: 5px;
// }
// }
// .success-text{
// color: $success-color;
// }
// .error-text{
// color: $error-color;
// }
}
}
}