123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /* eslint-disable prefer-template,no-param-reassign */
- import React, { Component } from 'react';
- import { Upload, Icon, message, Modal } from 'antd';
- import { queryOssSignature } from '../../services/resource';
- import { Hotax } from '../../utils/config';
- import { setSignature } from '../../utils/signature';
- import styles from './index.less';
- const Message = message;
- // 允许上传的文件类型
- const renderAccept = (accept) => {
- if (!accept) {
- return null;
- }
- if (['image', 'video', 'audio'].find(ext => ext === accept)) {
- return `${accept}/*`;
- }
- if (accept === 'zip') {
- return 'application/zip,application/x-zip,application/x-zip-compressed';
- }
- return `.${accept}`;
- };
- // 检查文件大小
- const checkFileSize = (fileName, fileSize) => {
- if (fileSize > Hotax.FILE_MAX_SIZE * 1000 * 1000) {
- Message.error(`${fileName}文件大小超过${Hotax.FILE_MAX_SIZE}M!`);
- return false;
- }
- return true;
- };
- /**
- * 使用时间戳生成随机的文件名
- * @param fileName
- * @param fileCode
- * @returns {string}
- */
- const getRandomFileName = (fileName, fileCode) => {
- const relativePath = fileCode ? fileCode.replace(/-/g, '/') + '/' : '';
- const separatorIndex = fileName.lastIndexOf('.');
- const suffix = fileName.substring(separatorIndex + 1, fileName.length);
- const randomFileName = (new Date()).getTime().toString() + Math.floor(Math.random() * 10000) + '.' + suffix;
- return `${relativePath}${randomFileName}`;
- };
- /**
- * 将传入文件对象处理成upload组件格式
- * @return {Array} [{}]
- */
- const renderFileList = (fileList) => {
- return fileList.map((file, index) => {
- if (file.status === 'uploading') {
- return file;
- }
- return {
- url: file.url,
- path: file.path,
- thumbUrl: file.url,
- name: file.name,
- size: file.size,
- type: file.type,
- status: 'done',
- uid: index,
- processed: true, // 标记是否图片已处理
- };
- });
- };
- class Uploader extends Component {
- constructor(props) {
- super(props);
- this.state = {
- ossSign: {}, // 保存oss签名
- fileList: renderFileList(this.props.fileList), // 文件对象列表
- curFileName: '',
- previewImg: '',
- previewVisible: false,
- };
- }
- handleBeforeUpload = (file) => {
- const { fileCode } = this.props;
- if (!checkFileSize(file.name, file.size)) {
- return false;
- }
- return queryOssSignature({ fileName: file.name })
- .then((res) => {
- this.setState({
- ossSign: res.data || res,
- curFileName: getRandomFileName(file.name, fileCode),
- });
- if (res.data) {
- setSignature(res.data); // 保存签名到本地
- }
- });
- };
- handleOnChange = ({ fileList }) => {
- const { ossSign, curFileName } = this.state;
- const { onUpload, totalLimit } = this.props;
- const { dir, host } = ossSign;
- const newFileList = fileList.filter((file) => {
- if (file.status === 'error') {
- Message.error(`${file.name}上传失败!`); // 上传失败给出提示并去掉
- return false;
- }
- if (file.status === 'done' && !file.processed) {
- Message.success('上传成功');
- file.url = `${host}/${dir}${curFileName}`;
- file.path = `${dir}${curFileName}`;
- file.thumbUrl = file.url;
- file.processed = true;
- }
- return true;
- });
- this.setState({
- fileList: renderFileList(newFileList),
- });
- const uploaded = newFileList.filter((file) => {
- return file.status === 'done' && file.processed;
- });
- if (!uploaded.length) { return; }
- if (this.props.onChange) {
- this.props.onChange(uploaded.splice(0, totalLimit));
- } else {
- onUpload(uploaded.slice(0, totalLimit));
- }
- };
- handleOnRemove = (file) => {
- const newFileList = this.state.fileList.filter((item) => {
- return item.uid !== file.uid;
- });
- if (this.props.onChange) {
- this.props.onChange(newFileList);
- } else {
- this.props.onRemove(newFileList);
- }
- };
- handleOnPreview = (file) => {
- this.setState({
- previewImg: file.url || file.thumbUrl,
- previewVisible: true,
- });
- };
- handleCancelPreview = () => {
- this.setState({
- previewVisible: false,
- });
- };
- render() {
- const { multiple, accept, totalLimit, forbidden } = this.props;
- const { ossSign, fileList, curFileName, previewImg, previewVisible } = this.state;
- const { host, policy, accessid, signature, dir } = ossSign;
- const uploadProps = {
- action: host,
- headers: {
- Authorization: `OSS${accessid}:${signature}`,
- },
- data: {
- policy,
- signature,
- OSSAccessKeyId: accessid,
- key: `${dir}${curFileName}`,
- success_action_status: '200',
- },
- fileList,
- multiple,
- disabled: !!(forbidden || this.state.fileList.length >= totalLimit),
- accept: renderAccept(accept),
- listType: 'picture',
- beforeUpload: this.handleBeforeUpload,
- onPreview: this.handleOnPreview,
- onChange: this.handleOnChange,
- onRemove: this.handleOnRemove,
- };
- return (
- <div>
- <Upload.Dragger {...uploadProps}>
- <p className={styles.dragIcon}>
- <Icon type="inbox" />
- </p>
- <p className={styles.dragText}>点击或者拖拽图片到此区域进行上传</p>
- <p className={styles.dragHint}>{`支持jpg/png/svg等图片格式,大小需小于${Hotax.FILE_MAX_SIZE}M`}</p>
- </Upload.Dragger>
- <Modal
- visible={previewVisible}
- footer={null}
- onCancel={this.handleCancelPreview}
- width={1100}
- >
- <img src={previewImg} alt="" style={{ width: '100%', marginTop: 20 }} />
- </Modal>
- </div>
- );
- }
- }
- export default Uploader;
|