antd upload
相信大家在上传文件、头像、图片的时候,第一时间想到的都是antd upload。
下面是我从antd拿过来的upload的属性。
限制上传文件格式.rar、.zip、.doc、.docx、.pdf
我们一般用来对于限制上传文件格式的属性是accept,但是在开发的过程中,博主发现了,accept对于.doc、.docx、.pdf、.png、.jpg、.rar,格式的限制是完全没有问题的。但是对于.zip的限制就有问题了,当我属性设置为 accept=".rar,.zip,.doc,.docx,.pdf"的时候,只要有.zip,上传文件的格式就会支持.xmind、.xlsx格式,上传的时候就不会报错,会上传成功,这肯定是不行的,这个时候,我们就需要在beforeUpload这个属性中去做上传文件的限制。
beforeUpload是upload上传文件之前的钩子,参数为上传的文件,若返回 false 则停止上传。我们在beforeUpload函数的file参数中可以获取上床文件的文件信息,这个时候我们就可以根据file里面的参数来进行判断。
注意:博主为什么要用file.name的后缀来匹配他的文件类型,也是是在是没有办法。file有个type属性,表示文件类型,但是docx后缀的文件没有type类型,为了支持上传docx文件,所以,只能用下面的方法来实现:代码如下:
通过file.type来判断上传文件类型(无法判断.docx文件)
const isJpgOrPng = file.type === 'application/zip' || file.type === 'application/wps-writer' || file.type === 'application/pdf' || file.type === 'application/x-rar';
if (!isJpgOrPng) {
message.error('仅支持文件格式:.rar、.zip、.doc、.docx、.pdf格式图片!');
this.onRemove(file);
return
}
通过file.name来判断上传文件类型(适用于所有文件)
avatarBeforeUpload = file => {
let fileType = file.name.split('.');
const fileDate = fileType.slice(-1);
if (['zip', 'rar', 'doc', 'docx', 'pdf'].indexOf(fileDate[0]) < 0) {
message.error('仅支持文件格式:.rar、.zip、.doc、.docx、.pdf格式附件!');
this.setState({
file
})
this.onRemove(file);
return false
}
};
限制上传文件大小不能大于200M
同样是在beforeUpload里面来做限制,下面是支持文件格式:.rar、.zip、.doc、.docx、.pdf并且不能大于200M的代码
avatarBeforeUpload = file => {
let fileType = file.name.split('.');
const fileDate = fileType.slice(-1);
if (['zip', 'rar', 'doc', 'docx', 'pdf'].indexOf(fileDate[0]) < 0) {
message.error('仅支持文件格式:.rar、.zip、.doc、.docx、.pdf格式附件!');
this.setState({
file
})
this.onRemove(file);
return
}
const isLt200M = file.size / 1024 / 1024 < 200;
if (!isLt1M) {
message.error('附件大小不能超过200M!');
this.setState({
file
})
this.onRemove(file);
return
}
return isLt200M;
};
限制上传文件大于200M并且不是.rar、.zip、.doc、.docx、.pdf的文件,不调用接口,只有满足条件的文件才能调用接口
这里就用到了customRequest属性,customRequest是通过覆盖默认的上传行为,可以自定义自己的上传实现,我们在这里,可以对于调用接口和传参进行限制,代码如下:
customRequest = async ({ action, method, file, onProgress, onSuccess, onError, }) => {
// const { onChange } = this.props;
const formData = new FormData();
formData.append('file', file);
const fileData = this.state.file;
// 当要上传的文件名和之前不满足条件的文件名进行匹配,相同的话,代码终止,不往下继续执行。
if(file.name == fileData.name){
return
}
try {
const { data } = await axios.post(action, formData, {
processData: false,
noContentType: true,
onUploadProgress: function (progressEvent) {
if (progressEvent.lengthComputable) {
let percent = Math.ceil((progressEvent.loaded / progressEvent.total) * 100);
onProgress({
percent,
});
}
},
});
onSuccess();
// if (isFunction(onChange)) {
// // onChange(data.data);
this.props.form.setFieldsValue({ 'filePath': data.data })
// }
this.setState({
file: {},
})
} catch (e) {
console.log(e);
onError(e);
}
}
调用后端接口删除文件
实现这个功能就需要用到onChange,onChange上传中、完成、失败都会调用这个函数。 当info.file.status === "removed"状态时候,调用removeFile方法,删除文件**。onRemove点击移除文件时的回调,返回值为 false 时不移除。** 要实现删除文件这个功能这需要三个方法来互相配合,在avatarBeforeUpload方法中又看到调用onRemove方法,这时候,文件的状态会变成removed。在文件变化时,会去调用changeImg方法,在changeImg中,代码会走到info.file.status === “removed”,然后去调用删除文件接口,大功告成,代码如下:
// 删除文件
removeFile = () => {
const fileId = this.props.form.getFieldValue('filePath');
// console.log(fileId, 'fileId---')
let params = {
fileId: fileId,
}
axios.post("/api/tpc/tpc/expertJudgement/removeFile", params).then(res => {
if (res.data.code == 200) {
message.success(res.data.data || '删除成功')
} else {
message.error(res.data.message || '删除失败')
}
}).catch(err => {
// console.log(err, 'err')
})
};
//上传文件
changeImg = info => {
// console.log(info, 'inf----')
const { file } = this.state;
let fileList = info.fileList.slice(-1);;
fileList.forEach((file) => {
if (file.response) {
file.url = file.response.url;
}
});
const fileData = fileList.filter(item => item.name != file.name)
this.setState({ fileList: fileList.filter(item => item.name != file.name) }, () => {
});
if (info.file.status === "uploading") {
this.setState({ loading: true });
return;
}
if (info.file.status === "removed") {
this.removeFile();
this.setState({
loading: true
}, () => {
this.props.form.setFieldsValue({
'filePath': undefined
})
});
return false;
}
if (info.file.status === "done") {
this.setState({
imageUrl: info.file.thumbUrl,
loading: false,
avatarFlag: true,
})
}
};
onRemove = (file) => {
this.setState({ fileList: this.state.fileList.filter(item => item.name !== file.name) }, () => {
this.props.form.setFieldsValue({ fileList: this.state.fileList });
});
}
只能上传一个文件(新上传的文件替换之前的文件)
这时候就需要fileList这个属性了, fileList对列表进行完全控制,可以实现文件的自定义功能,上传列表数量的限制。
//上传文件
changeImg = info => {
// console.log(info, 'inf----')
const { file } = this.state;
//*************上传一个文件,并且这个文件永远是最新上传的文件*****************
let fileList = info.fileList.slice(-1);;
fileList.forEach((file) => {
if (file.response) {
file.url = file.response.url;
}
});
const fileData = fileList.filter(item => item.name != file.name)
this.setState({ fileList: fileList.filter(item => item.name != file.name) }, () => {
//*************上传一个文件*****************
if (info.file.status === "uploading") {
this.setState({ loading: true });
return;
}
if (info.file.status === "removed") {
this.removeFile();
this.setState({
loading: true
}, () => {
this.props.form.setFieldsValue({
'filePath': undefined
})
});
return false;
}
if (info.file.status === "done") {
this.setState({
imageUrl: info.file.thumbUrl,
loading: false,
avatarFlag: true,
})
}
};
完整代码如下
import React, { Component } from 'react';
import { Button, Form, message,Col, Upload, } from 'antd';
import { axios } from '@/utils/request';
import style from './index.less'
const formItemLayout = {
labelCol: {
xs: { span: 20 },
sm: { span: 2 },
},
wrapperCol: {
xs: { span: 20 },
sm: { span: 20 },
},
};
class add extends Component {
constructor(props) {
super(props);
this.state = {
fileList: [],
file: '',
detailDate: {}, // 详情
}
this.formLayout = {
labelCol: { span: 10 },
wrapperCol: { span: 14 },
};
// const
}
componentDidMount() {
}
//上传文件
changeImg = info => {
// console.log(info, 'inf----')
const { file } = this.state;
let fileList = info.fileList.slice(-1);;
fileList.forEach((file) => {
if (file.response) {
file.url = file.response.url;
}
});
const fileData = fileList.filter(item => item.name != file.name)
this.setState({ fileList: fileList.filter(item => item.name != file.name) }, () => {
// console.log(this.state.fileList, 'fileList----', file, 'fileData', fileData)
// this.props.form.setFieldsValue({ fileList: fileList });
});
// this.setState({
// fileList: fileList
// });
if (info.file.status === "uploading") {
this.setState({ loading: true });
return;
}
if (info.file.status === "removed") {
this.removeFile();
this.setState({
loading: true
}, () => {
this.props.form.setFieldsValue({
'filePath': undefined
})
});
return false;
}
if (info.file.status === "done") {
this.setState({
imageUrl: info.file.thumbUrl,
loading: false,
avatarFlag: true,
})
}
};
customRequest = async ({ action, method, file, onProgress, onSuccess, onError, }) => {
// const { onChange } = this.props;
const formData = new FormData();
formData.append('file', file);
const fileData = this.state.file;
if (file.name == fileData.name) {
return
}
try {
const { data } = await axios.post(action, formData, {
processData: false,
noContentType: true,
onUploadProgress: function (progressEvent) {
if (progressEvent.lengthComputable) {
let percent = Math.ceil((progressEvent.loaded / progressEvent.total) * 100);
onProgress({
percent,
});
}
},
});
onSuccess();
// if (isFunction(onChange)) {
// // onChange(data.data);
this.props.form.setFieldsValue({ 'filePath': data.data })
// }
this.setState({
file: {},
})
} catch (e) {
console.log(e);
onError(e);
}
}
avatarBeforeUpload = file => {
let fileType = file.name.split('.');
const fileDate = fileType.slice(-1);
if (['zip', 'rar', 'doc', 'docx', 'pdf'].indexOf(fileDate[0]) < 0) {
message.error('仅支持文件格式:.rar、.zip、.doc、.docx、.pdf格式附件!');
this.setState({
file
})
this.onRemove(file);
return
}
const isLt1M = file.size / 1024 / 1024 < 200;
if (!isLt1M) {
message.error('附件大小不能超过200M!');
this.setState({
avatarFlag: false,
file
})
this.onRemove(file);
return
}
return isLt1M;
// return isJpgOrPng && isLt1M;
};
onRemove = (file) => {
this.setState({ fileList: this.state.fileList.filter(item => item.name !== file.name) }, () => {
this.props.form.setFieldsValue({ fileList: this.state.fileList });
});
}
// 删除文件
removeFile = () => {
const fileId = this.props.form.getFieldValue('filePath');
// console.log(fileId, 'fileId---')
let params = {
fileId: fileId,
}
axios.post(url, params).then(res => {
if (res.data.code == 200) {
message.success(res.data.data || '删除成功')
} else {
message.error(res.data.message || '删除失败')
}
}).catch(err => {
// console.log(err, 'err')
})
};
render() {
const {
form: { getFieldDecorator },
} = this.props;
return (
<div className={styles.myOrder}>
<div className={style.exportAnswer}>
<Form {...formItemLayout}>
<Row>
<Col span={24}>
<Form.Item label="添加文件">
{getFieldDecorator('filePath', {
})(
<Upload
accept='.rar,.zip,.doc,.docx,.pdf,'
action='url' //后端提供的upload接口,返回url
beforeUpload={this.avatarBeforeUpload}
onChange={this.changeImg}
multiple={false}
method="POST"
customRequest={this.customRequest}
className='upload-list-inline'
fileList={this.state.fileList}
>
<Button>
上传文件
</Button>
</Upload>
)}
</Form.Item>
</Col>
</Row>
</Form>
</div>
</div >
);
}
}
export default Form.create()(add);