import createReactClass from 'create-react-class'; import PropTypes from 'prop-types'; import React from 'react'; import ReactDOM from 'react-dom'; import request from 'superagent-bluebird-promise'; import { lastToken } from '../utils/qiniu'; const isFunction = (fn: any) => { const getType = {}; return fn && getType.toString.call(fn) === '[object Function]'; }; // TODO Optimize file upload export const Upload = (file: any, token, prefix = '', key = '') => { const uploadUrl = 'https://up.qbox.me/'; const innerFile = file; innerFile.preview = URL.createObjectURL(innerFile); let innerKey = key; if (!innerKey) { innerKey = `${innerFile.preview.split('/').pop()}.${innerFile.name.split('.').pop()}`; } if (prefix) { innerKey = prefix + innerKey; } if (!token) { return request.console.error('Token undefined'); } return request .post(uploadUrl) .field('key', innerKey) .field('token', token) .field('x:filename', file.name) .field('x:size', file.size) .attach('file', file, file.name) .set('Accept', 'application/json'); }; // eslint-disable-next-line react/prefer-es6-class const ReactQiniu = createReactClass({ // based on https://github.com/paramaggarwal/react-dropzone // eslint-disable-next-line react/no-unused-class-component-methods propTypes() { return { onDrop: PropTypes.func.isRequired, // called before upload to set callback to files onUpload: PropTypes.func, size: PropTypes.number, style: PropTypes.object, supportClick: PropTypes.bool, accept: PropTypes.string, multiple: PropTypes.bool, // Qiniu uploadKey: PropTypes.string, prefix: PropTypes.string, onRefreshQiniuToken: PropTypes.func, }; }, getDefaultProps() { return { supportClick: true, multiple: true, }; }, getInitialState() { return { isDragActive: false, }; }, onDragLeave() { this.setState({ isDragActive: false, }); }, onDragOver(e: any) { e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; // eslint-disable-line this.setState({ isDragActive: true, }); }, onDrop(e: any) { e.preventDefault(); this.setState({ isDragActive: false, }); let files; if (e.dataTransfer) { files = e.dataTransfer.files; } else if (e.target) { files = e.target.files; } const maxFiles = this.props.multiple ? files.length : 1; if (this.props.onUpload) { files = Array.prototype.slice.call(files, 0, maxFiles); this.props.onUpload(files, e); } // var maxSizeLimit = formatMaxSize(this.props.maxSize) lastToken(this.props.onRefreshQiniuToken).then((token) => { for (let i = 0; i < maxFiles; i += 1) { // if( maxSizeLimit && files[i].size > maxSizeLimit){ // console.trace && console.trace(new Error('文件大小错误!')) // this.props.onError && this.props.onError({ // coed:1, // message:'上传的文件大小超出了限制:' + this.props.maxSize // }) // }else{ files[i].request = this.upload(files[i], token); files[i].uploadPromise = files[i].request.promise(); // } } if (this.props.onDrop) { files = Array.prototype.slice.call(files, 0, maxFiles); this.props.onDrop(files, e); } }); }, onClick() { if (this.props.supportClick) { this.open(); } }, open() { const fileInput: any = ReactDOM.findDOMNode(this.refs.fileInput); // eslint-disable-line fileInput.value = null; fileInput.click(); }, upload(file: any, token: string) { if (!file || file.size === 0) return null; const r = Upload(file, token, this.props.prefix, this.props.uploadKey); if (isFunction(file.onprogress)) { r.on('progress', file.onprogress); } return r; }, render() { let className = this.props.className || 'dropzone'; const { borderStyle } = this.props; if (this.state.isDragActive) { className += ' active'; } const style = this.props.style || { width: this.props.size, height: this.props.size, borderStyle: borderStyle || (this.state.isDragActive ? 'solid' : 'dashed'), }; return React.createElement( 'div', { className, style, onClick: this.onClick, onDragLeave: this.onDragLeave, onDragOver: this.onDragOver, onDrop: this.onDrop, }, React.createElement('input', { style: { display: 'none' }, type: 'file', multiple: this.props.multiple, ref: 'fileInput', onChange: this.onDrop, accept: this.props.accept, }), this.props.children ); }, }); export default ReactQiniu;