UNPKG

lm-upload

Version:

* 作者:quying * 邮箱:qy9404@163.com * 版本:**`0.2.0`**

255 lines (211 loc) 7.09 kB
/** * Created by quying<qy9404@163.com>. * ComponentName Upload * Desc 组件描述内容 * GroupName lm-component */ import React, { Component } from 'react' import PropTypes from 'prop-types' import classNames from 'classnames' import './index.scss' import getUid, { initFileList } from './uid'; import defaultUpload from './request'; /** * @class Upload * @extends React.Component * @desc Upload Component for mobile */ export default class Upload extends Component { static propTypes = { name: PropTypes.string, //文件名 accept: PropTypes.string, //接受的文件类型 multiple: PropTypes.bool, //是否支持多选文件 onInputChange: PropTypes.func, //(files) = > boolean | Promise beforeUpload: PropTypes.func, //(file, fileList) => boolean | Promise customUpload: PropTypes.func, //通过覆盖默认的上传行为,可以自定义自己的上传实现 disabled: PropTypes.bool, //是否禁用 action: PropTypes.string, //上传的地址 data: PropTypes.oneOfType([ //表单数据 PropTypes.object, PropTypes.func ]), headers: PropTypes.object, //xhr请求头 onStart: PropTypes.func, //开始上传回调 onProgress: PropTypes.func, //上传进度 onProgress(e, file) onSuccess: PropTypes.func, //上传成功回调 onSuccess(ret, file, xhr) withCredentials: PropTypes.bool, //允许跨域发送cookie appUpload: PropTypes.func, //调用app上传 }; static defaultProps = { multiple: false, disabled: false, isApp: false, onStart: ()=>{}, beforeUpload: ()=>{}, onError: ()=>{} }; reqs = {} /** * @constructor */ constructor(props) { super(props); this.state = { uid: getUid() } this.changeHandler = this.changeHandler.bind(this); } componentDidMount() { this._isMounted = true; } componentWillUnmount() { this._isMounted = false; this.abort(); } onClick = () => { const { appUpload } = this.props; if(appUpload) { return appUpload(); } const el = this.fileInput; if(!el) { return; } el.click(); } changeHandler(e){ const files = e.target.files; const { onInputChange } = this.props; if(onInputChange) { const changedRet = onInputChange(files); if (changedRet && changedRet.then) { changedRet.then((processedFiles) => { this.uploadFiles(processedFiles); }).catch(e => { console && console.log(e); }); } else if (changedRet !== false) { this.uploadFiles(changedRet); } } else { this.uploadFiles(files); this.reset(); } e.target.value = ''; } uploadFiles(files) { let fileList = Array.prototype.slice.call(files); fileList.forEach((file) => { file.uid = getUid(); this.upload(file, fileList); }); } upload(file, fileList) { const { props } = this; if(!props.beforeUpload) { this.post(file); } //返回 false 则停止上传。支持返回一个 Promise 对象,Promise 对象 reject 时则停止上传,resolve 时开始上传 const before = props.beforeUpload(file, fileList); if (before && before.then) { before.then((processedFile) => { const processedFileType = Object.prototype.toString.call(processedFile); if(processedFileType === '[object String]' || processedFileType === '[object Blob]') { this.post(file, processedFile); } else { this.post(file); } }).catch(e => { console && console.log(e); }); } else if (before !== false) { this.post(file); } } post(file, processedFile) { if (!this._isMounted) { return; } let { data } = this.props; if (typeof data === 'function') { let dataRet = data(file); if(dataRet.then) { dataRet.then(ret => { data = ret; this.send(data, file, processedFile); }) } else { data = dataRet; this.send(data, file, processedFile) } } } send(data, file, processedFile) { const { props } = this; const { uid } = file; const { onStart, onProgress } = props; const request = props.customUpload || defaultUpload; this.reqs[uid] = request({ action: props.action, filename: props.name, file: processedFile || file, data, headers: props.headers, withCredentials: props.withCredentials, onProgress: onProgress ? e => { onProgress(e, file); } : null, onSuccess: (ret, xhr) => { delete this.reqs[uid]; props.onSuccess(ret, file, xhr); }, onError: (err, ret) => { delete this.reqs[uid]; props.onError(err, ret, file); }, }); onStart(file); } reset() { this.setState({ uid: getUid() }) } abort(file) { const { reqs } = this; if(file) { let uid = file; if(file.uid) { uid = file.uid; } if(reqs[uid]) { reqs[uid].abort(); delete reqs[uid]; } } else { Object.keys(reqs).forEach((uid) => { if(reqs[uid]) { reqs[uid].abort(); } delete reqs[uid]; }) } } render () { let { className, accept, multiple, disabled, children, style } = this.props; return ( <span className={ className } onClick={ this.onClick } style={style}> <input type="file" ref={ (node) => this.fileInput = node } style={{ display: 'none'}} accept={ accept } multiple={ multiple } disabled={ disabled } onChange={ this.changeHandler } /> { children } </span> ) } } Upload.initFileList = initFileList;