React实现文件上传带进度条以及onDrag拖拽文件上传

2020-04-242653次阅读javascript

CSS3彩色进度条加载动画带进度百分比看这里

 

拖拽事件

onDragEnter :拖拽的物体进入时触发

onDragOver :拖拽的物体在区域中拖动时持续触发

onDragLeave :拖拽的物体离开区域时触发

onDrop :拖拽的物体放置在区域中时触发

import React from 'react';
import Layer from '../Layer';

let xhr = new XMLHttpRequest();

export default class extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            status:0,//0是选择文件,1是上传文件中
            filename:'',
            fileSize:0,
            progress:0,
            dropStaus:false,
            msg:'',
            urlData:[]
        };
    }

    componentDidMount() {

        document.ondrop = function(e){
            e.preventDefault();
        };

        
        const str = localStorage.getItem('saveData');

        let ary =  str ? str.split('|||'):[];


        if(str){

            this.setState({
                urlData:ary.reverse().slice(0,3)
            });

        }

    }

    componentWillUnmount() {
    }

    tips(msg){
        this.setState({
            msg
        });
        setTimeout(()=>{
            this.setState({
                msg:''
            });
        },1500)
    }
    
    uploadFile(event,drop){

        if(this.state.status) return;

        event.persist();

        let file;

        if(drop){
            event.preventDefault();
            file = event.dataTransfer.files[0];
        }else{
            file = event.currentTarget.files[0];
        }


        if(!/zip/.test(file.type)){

            this.tips('请选择zip文件');

            return;
        }
        
        
        let fileSize = 0;

        if (file.size > 1024 * 1024){
            fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
        }else{
            fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';
        }
        this.setState({
            status: 1,
            filename:file.name,
            fileSize
        });

        var fd = new FormData();

        fd.append("file",file);

        

        xhr.upload.addEventListener("progress",event=>{
            this.uploadProgress(event);
        });

        xhr.addEventListener("load",event=>{
            this.uploadComplete(event);
        });

        xhr.addEventListener("error",event=>{
            this.uploadFailed(event);
        });

        xhr.addEventListener("abort",event=>{
            this.uploadCanceled(event);
        });

        xhr.open("POST", "/dev/api/upload");//修改成自己的接口

        xhr.send(fd);


    }

    uploadProgress(evt) {

        let progress;

        if (evt.lengthComputable) {

            progress = Math.round(evt.loaded * 100 / evt.total) + '%';

        }else{

            progress = '100%'

        }

        this.setState({
            progress
        });

    }
    
    uploadComplete(evt) {

        console.log(evt,'服务器端返回响应时候触发event事件');

        const {code,message,data} = JSON.parse(evt.target.responseText);

        if(code != 200){

            this.tips(message);

            this.setState({
                status:0
            });

            return;
        }



        this.props.updataParent(data);





        /* 服务器端返回响应时候触发event事件*/
        //document.getElementById('result').innerHTML = evt.target.responseText;
    }
    
    uploadFailed(event){

        console.log(event,'上传文件时出错');

    }

    uploadCanceled(event) {

        event.preventDefault();

        this.setState({
            status:0
        });

        console.log(event,'已取消上传,或浏览器已断开连接。');
    }

    dragenter(e){

        e.preventDefault();

        if(this.state.status) return;

        this.setState({
            dropStaus:true
        });


    }

    dragleave(e){

        e.preventDefault();

        if(this.state.status) return;

        this.setState({
            dropStaus:false
        });
        
    }


    render(){

        const borderStyle = {
            borderColor:this.state.dropStaus?'#ffa800':'#D7D7D7'
        };

        return(
            <React.Fragment>
            <div className="updataHeader">上传文件</div>
            <div className="updataWrap column" style={borderStyle} onDrop={(e)=>this.uploadFile(e,'drop')} onDragEnter={(e)=>this.dragenter(e)}  onDragLeave={(e)=>this.dragleave(e)} onDragOver={(e)=>e.preventDefault()}>
                {
                    !this.state.status ? <div className="updataStart">
                        <a href="#" className="updataBtn"><input type="file" accept="application/zip" onChange={(e)=>this.uploadFile(e)} /></a>
                        <p>点击按钮选择压缩包(包含index.html),或拖拽文件到此区域<br/>(支持zip文件)</p>
                    </div>:<div className="updataMiddle">
                        <h2>正在上传中,请不要关闭浏览器</h2>
                        <p className="progressWrap"><i style={{width:this.state.progress}}></i></p>
                        <p>{this.state.filename}<span>{this.state.progress} / {this.state.fileSize}</span></p>
                        <a href="#" className="canceledBtn" onClick={e=>xhr.abort()}>取消</a>
                    </div>
                }
            </div>
            {!this.state.status&&this.state.urlData.length?<dl className="recentlyuploaded">
                    <dt>最近上传:</dt>
                    {
                        this.state.urlData.map(item =>
                            <dd key={item}><a href={item}  onClick={e=>this.props.setIframeUrl(e,{loader:item})}>{item}</a></dd>
                        )
                    }
                </dl>:null}
            {this.state.msg?<Layer msg={this.state.msg} />:null}
            </React.Fragment>
        );
    }

};

 

上一篇: react使用qrcode.react生成二维码  下一篇: React弹出层组件一  

React实现文件上传带进度条以及onDrag拖拽文件上传相关文章