Uploader.js 8.7 KB
import React,{PropTypes} from 'react'; 
import {Button,Row,Col,ProgressBar} from 'react-bootstrap'; 
import {LinearProgress} from 'material-ui'  
import cx from 'classnames'; 
import s from './Uploader.scss';
import * as fetch from '../../utils/fetch';  

export class Uploader extends React.Component { 
	constructor(props) {
        super(props);
        this.getCallbackFiles=this.getCallbackFiles.bind(this);
        this.checkMaxFile=this.checkMaxFile.bind(this);
        this.state={
        	files:[],
        	showHelp:false,
        	submitFlag:false
        }   

    }
    static propTypes = {  
    	type: PropTypes.string,
    	maxFileSize:PropTypes.number,
    	onChange:PropTypes.func,
    	backResult:PropTypes.func,
    	placeholder:PropTypes.string,
    	autoUpload:PropTypes.bool
	} 
	static defaultProps = {  
    	maxFileSize:10
	}
	checkMaxFile(arrayFiles){  
		const {maxFileSize}=this.props,self=this;
		const {files}=this.state;
		if((files.length+arrayFiles.length)==maxFileSize){
			this.uploader.disableBrowse(true);
			self.setState({showHelp:true});
			return false;
		}else if((files.length+arrayFiles.length)<maxFileSize){ 
			return false;
		}else if((files.length+arrayFiles.length)>maxFileSize||arrayFiles.length>maxFileSize){
			arrayFiles.map(file=>{
				self.uploader.removeFile(file);
			})
			self.setState({showHelp:true});
			return true;
		} 
	}
	freshToken(params){  
  		return fetch.post('/getUploaderToken',params)
	}
	getCallbackFiles(filesArray){
		const self=this;
		let {files}=this.state;
		const token=self.uploader.ossToken;
		if(filesArray&&filesArray.length>0)
			files=filesArray;
		if(files.length<1){
			return [];
		}else if(token){
			const tempFile=[];
			files.map((file,i)=>{ 
				tempFile.push({
					id:file.id,
					file_id:file.file_id,
					name:file.name,
					type:file.type,
					size:file.size,
					bucket:token.bucket,
					path:token.object_path,
					requestId:token.request_id,
					status:file.status+""
				})
			});
			return tempFile;
		}else{
			const tempFile=[];
			files.map((file,i)=>{ 
				tempFile.push({
					id:file.id,
					file_id:file.file_id,
					name:file.name,
					type:file.type,
					size:file.size,
					status:file.status+""
				})
			});
			return tempFile;
		}
	}
	uploadBtn(){
		const self=this;
		const {type}=this.props;  
		const {files}=this.state;
		if(files.length<1||(this.uploader.total&&this.uploader.total.queued==0))
			return
		this.freshToken({
			'action':'put_object',
			'object_type':type,
			'instance_id':'', 
			'access_type':'web_upload'
		}).then(data=>{  
			self.uploader.ossToken=data;
			self.uploader.setOption({
	            'url': 'https://'+data.bucket+"."+data.domain+'/',//+data.object_path,//data.host,
	            'multipart_params':{
	            	OSSAccessKeyId:data.access_key_id,
	            	key : data.object_path + '${filename}',
	            	policy:data.policy,
	            	signature:data.signature,
	            	callback:data.callback_body,
	            	'x:access_token': data.callback_token,
	            	success_action_status:'200'
	            } 
	        });
			self.uploader.start(); 
		}).catch(err => { throw err; }); 
	}	
	removeOSSFile(file){
		const token=this.uploader.ossToken,self=this;
		const removeFiles=()=>{
			const filesArray=[];
			const {maxFileSize}=self.props;
			const {files}=self.state;
			files.map((upFile,index)=>{ 
		      	if(upFile.id!=file.id){ 
		      		filesArray.push(upFile)
		      	}else{
		      		self.uploader.removeFile(file);
		      	}
		    });   
			if(filesArray.length<maxFileSize){
				self.uploader.disableBrowse(false);
				self.setState({
					'files':filesArray,
					showHelp:false
				});
			}else
				self.setState({
					'files':filesArray
				}); 
		}
		fetch.post('/delOSSObject',{
			name:file.name,
			request_id:token.request_id,
			bucket:token.bucket
		}).then(data=>{
        	console.log(data);
        	if(data){
        		removeFiles();
        	}
        }); 
	};
	removeFile(file,e){
		const filesArray=[],self=this;
		const {maxFileSize}=this.props;
		const {files}=this.state;
		if(file.status==6){
			this.removeOSSFile(file);
		}else{
		    files.map((upFile,index)=>{ 
		      	if(upFile.id!=file.id){ 
		      		filesArray.push(upFile)
		      	}else{
		      		self.uploader.removeFile(file);
		      	}
		    });   
			if(filesArray.length<maxFileSize){
				this.uploader.disableBrowse(false);
				this.setState({
					'files':filesArray,
					showHelp:false
				});
			}else
				this.setState({
					'files':filesArray
				});
		}
	}
	componentDidUpdate(prevProps, prevState){
		const files=this.state.files,self=this;
		const nextFiles=prevState.files;
		const {autoUpload}=this.props;
		if(files.length!=nextFiles.length){
			self.props.onChange(self.getCallbackFiles());
			self.props.backResult(self.uploader.total);
		}
		if(autoUpload&&files.length>0&&this.state.submitFlag){
			this.uploadBtn();
		}
	}
	componentDidMount(){  
		console.log("load ok!");
		const self=this; 
		this.uploader = new plupload.Uploader({
			runtimes : 'html5,flash,silverlight,html4',
			browse_button :  'selectfiles', 
			container: self.refs['file_uploader_wrap'], 
 			url : 'https://oss.aliyuncs.com', 
			init: {
			    PostInit: function() {
			      console.log('@@@@@');
			    }, 
			    FilesAdded: function(up, files) { 
			    	
			    	if(self.checkMaxFile(files))
			    		return;
			    	const filesArray=self.state.files.concat(files); 
			        self.setState({
			       		'files':filesArray,
			       		'submitFlag':true 
			        });  
			    }, 
			    UploadProgress: function(up, file) { console.log('uploading');
			    	const filesArray=[];
				    self.state.files.map((upFile,index)=>{ 
				      	if(upFile.id==file.id){
				      		filesArray.push(file); 
				      	}else{
				      		filesArray.push(upFile)
				      	}
				    });  
					self.setState({
						'files':filesArray,
						'submitFlag':false 
					});
			    }, 
			    FileUploaded: function(up, file, info) {
			            console.log('uploaded')
			            console.log(info.status) 
			            console.log(file) 
			            if (info.status == 200&&info.response)
			            { 	
			            	const fileInfo=JSON.parse(info.response);
			            	file['file_id']=fileInfo.uuid;
			                console.log('success');
			            }
			            else
			            {
			            	 console.log(info.response); 
			            } 
			    }, 
			    UploadComplete:function(up, files) { 
			    	console.log(self.getCallbackFiles(files));
			    	self.props.onChange(self.getCallbackFiles(files));
			    	console.log(self.uploader.total);
			    	self.props.backResult(self.uploader.total); 
			    },
			    Error: function(up, err) {
			       console.log(err);
			    }
			}
		});
		this.uploader.init(); 
	} 
	componentWillUnmount() {
		console.log("component remove!"); 
		this.uploader.destroy();
	}
    render(){
    	const {files,showHelp}=this.state,self=this;
    	const {maxFileSize,placeholder,autoUpload}=this.props;
    	const uploadDisable=files.length<1;
    	 
    	return (
    		<div className={cx(s.file_uploader_wrap,'form-group')}>
    			<div className={cx(s.tools_bar)}>
    				<a  id='selectfiles' className={cx(s.add_file,showHelp&&files.length>=maxFileSize?s.disabled:'')}><i className='fa fa-plus-circle'></i>选择文件</a> 
    				{!autoUpload&&
    					<a  className={cx(s.add_file,uploadDisable?s.disabled:'')} onClick={this.uploadBtn.bind(this)}><i  className={cx(!uploadDisable?s.upload_icon:'','fa','fa-upload')} title=''></i>开始上传</a> 
    				}
    			</div>
    			{(files.length<1&&placeholder)&&
	    			<div className={cx(s.placeholder_wrap,'form-control')}>
	    				{placeholder}
	    			</div>
    			}
    			<div ref='file_uploader_wrap'>
    				{files.map((file,index)=>{console.log(file.status);
    					if(file.status!=5)
	    					return ( 
	    						<Row className={cx(s.file_row)} key={index}> 
	    							<Col md={1} className={cx(s.action_wrap)}> 
	    								{file.status==1&&<i onClick={this.removeFile.bind(this,file)} className={cx(s.remove_icon,'kr_icon')} title=''>&#xe612;</i> }
	    							</Col>
	    							<Col md={4}  className={cx(s.file_linear)}>  
	    								<ProgressBar className={cx(s.uploader_progress_wrap)} striped active bsStyle="success" now={file.percent}  label="%(percent)s%"  /> 
	    							</Col>
	    							<Col md={2} className={cx(s.file_size_wrap)}>{plupload?plupload.formatSize(file.size):''}</Col> 
	    							<Col md={4}className={cx(s.file_name_wrap)}>{file.name}</Col>
	    						</Row>
	    					)
	    				else
	    					return null;
    				})}
    			</div>
    			{!autoUpload&&showHelp&&<span className="help-block" ><small>最多可以上传{this.props.maxFileSize}个文件</small></span>}
    		</div>
    	)
    }
}

 

export default Uploader;