zoukankan      html  css  js  c++  java
  • 原生API实现拖拽上传文件实践

    功能:

    拖拽上传文件、图片,上传的进度条,能够同时上传多个文件。

    完整的demo地址:https://github.com/qcer/FE-Components/tree/master/QDrag

    涉及到的API:

    1、HTML5的拖拽事件:dragenter,dragover,drop等

    2、XMLHttpRequest  Level2

    3、FormData

    4、(扩展:HTML5的File API)

    概述:

    1、利用拖拽实践的API将一个普通的div自定义成一个放置目标,这里有一个技巧是放置一个隐藏的input[type='file']的元素,在div上绑定input的点击事件,再点击事件中触发input的click事件,能够在div上任意位置达到type=file选择文件上传的效果。

    2、在div的drag事件中获取文件对象,通过FormData对象构造表单序列化的数据,同时动态生成页面元素,通过XMLHttpRequest对象发送数据,在xhr.upload的progress事件中实现上传进度的功能。

    3、后端通过nodejs实现一个http服务器,接受数据,进而可以扩展的解析数据。

    前端页面代码:

    <!DOCTYPE html>
    <html>
    <head>
        <title></title>
        <style type="text/css">
            #qdrag{
                height: 300px;
                width: 100%;
                background: #eee;
                border-radius: 5px;
                padding-top: 20px;
            }
            #qdrag-hidden {
                display: none;
                position: absolute;
                z-index: 10;
            }
            #qdrag .qdragzone{
                width: 100%;
                height: 50px;
                background: #ccc;
                line-height: 50px;
                border-bottom: 2px solid #fff;
                border-radius: 2px;
                overflow: hidden;
            }
    
            #qdrag .qdragzone img{
                margin-top: 9px;
                margin-left: 2%;
                margin-right: 4%;
                float: left;
            }
            #qdrag .qdragzone span{
                display: inline-block;
                font-weight: bold;
                font-size: 14px;
                float: left;
                width: 20%;
                color: #339966;
                font-family: "Times New Roman", Times, serif;
                 /*font-family:Arial,Helvetica,sans-serif;font-size:100%;*/
            }
            #qdrag .qdragzone progress{
                border-radius: 6px;
                height: 12px;
                width: 250px;
                color: #5cb85c;
                background:#fff;
            }
            progress::-moz-progress-bar { background: #fff;border-radius: 6px; }
            progress::-webkit-progress-bar { background: #fff;border-radius: 6px;}
    
            progress::-webkit-progress-value {background-color:#5cb85c;border-radius: 6px;}
            progress::-moz-progress-value { background-color:#5cb85c;border-radius: 6px;}
            }
        </style>
    </head>
    <body>
    
        <div id="qdrag">
            <input type="file" id="qdrag-hidden" name="image" value=""></input>
            <div class="qdragzone">
                <img src="./public/upload.png">
                <span>Name:test.txt</span>
                <span>Size:00000 Byte</span>
                <progress value="0.2" max="1">
            </div>
        </div>
        <script type="text/javascript">
            var qdrag = document.getElementById('qdrag');
            var qdrag_hidden = document.getElementById('qdrag-hidden');
            qdrag.onclick = function () { qdrag_hidden.click();}
            qdrag_hidden.onchange = function () {
                // body...
                var fileList = this.files;
                for (var i = 0; i < fileList.length; i++) {
                    sendFileByXHR('./upload.html',fileList[i]);
                }
            }
    
            function sendFileByXHR(url,fielObj) {
                // body...
                var xhr = new XMLHttpRequest();
                var newprogress = createTagsEle(fielObj).newprogress;
                xhr.upload.onprogress = function (event) {
                    // body...
                    console.log('xhr-loaded:'+event.loaded);
                    newprogress.setAttribute('value',event.loaded/event.total);
                }
                xhr.onreadystatechange = function () {
                    // body...
                    if (xhr.status === 200 && xhr.readyState === 4) {
                        console.log(xhr.responseText);
                    }
                }
                xhr.onabort = function (event) {
                    // body...
                    console.log('abort');
                }
                xhr.onerror = function (event) {
                    // body...
                    console.log('error');
                }
                var data = new FormData();
                data.append(fielObj.name,fielObj);
                xhr.open('POST',url,true);
                xhr.send(data);
    
            }
            function createTagsEle(fileObj) {
                // body...
                //create
                var fragment = document.createDocumentFragment();
                var newdiv = document.createElement('div');
                var newimg = document.createElement('img');
                var newspanName = document.createElement('span');
                var newspanSize = document.createElement('span');
                var newprogress = document.createElement('progress');
    
                //set attribute
                newdiv.setAttribute('class','qdragzone');
                newimg.setAttribute('src','./public/upload.png')
                newspanName.innerHTML = 'Name: ' + fileObj.name;
                newspanSize.innerHTML = 'Size: ' + fileObj.size+' Byte';
                newprogress.setAttribute('value',0);
                newprogress.setAttribute('max',1);
    
                //append
                fragment.appendChild(newdiv);
                newdiv.appendChild(newimg);
                newdiv.appendChild(newspanName);
                newdiv.appendChild(newspanSize);
                newdiv.appendChild(newprogress);
    
                // append to DOM
                qdrag.appendChild(fragment);
                return {newprogress};
            }
    
            qdrag.addEventListener('dragover',function (event) {
                // body...
                event.preventDefault();
            });
            qdrag.addEventListener('dragenter',function (event) {
                // body...
                event.preventDefault();
            });
            qdrag.addEventListener('drop',function (event) {
                // body...
                event.preventDefault();
                var fileList = Array.from(event.dataTransfer.files);
                for (var i = 0; i < fileList.length; i++) {
                    sendFileByXHR('./upload.html',fileList[i]);
                }
            });
            
        </script>
    </body>
    </html>

    后端代码:

    var http = require('http');
    var fs = require('fs')
    const PORT = 44444;
    const MIME = {
        default:'text/plain',
        html:'text/html',
        css:'text/css',
        js:'text/javascript',
        png:'image/png',
        jpg:'image/jpg',
        jpeg:'image/jpeg',
        json:'application/json',
        from:'multipart/form-data'
    }
    
    function handleStaticResource(req,res) {
        // body...
        var param = req.url.replace('/public','');
        var staticResource = fs.readFileSync('.'+param,'utf8');
    
        var fileType = req.url.split('/').pop().split('.').pop();
        switch(true){
            case ['js','css'].includes(fileType):
                res.setHeader('Content-Type',MIME[fileType]);
                break;
            case ['png','jpg','jpeg'].includes(fileType):
                staticResource = new Buffer(fs.readFileSync('.'+param,'base64'),'base64');
                console.log(fileType);
                res.setHeader('Content-Type',MIME[fileType]);
                break;
            default :
                res.setHeader('Content-Type',MIME['default']);
                console.log(MIME['default']);
                break;
        }
        res.end(staticResource);
    }
    
    var router = function (req,res) {
        // body...
        res.render = function (path,options) {
            // body...
            var content_html = fs.readFileSync(path,'utf8');
            res.writeHead(200,{'Content-Type':MIME['html']});
            res.end(new Buffer(content_html,'utf8'));
        }
    
        switch(true){
            case /^/public/([sS]*)/.test(req.url):
                handleStaticResource(req,res);
                break;
            case req.url === '/':
                // console.log(req.url);
                res.render('./testdrag.html');
                break;
            case req.url === '/upload.html':
                // console.log(req.headers);
                var buffers = [];
                req.on('data',function (chunk) {
                    // body...
                    buffers.push(chunk);
                })
                req.on('end',function () {
                    // body...
                    var data = Buffer.concat(buffers).toString();
                    res.end("ok");//正确的调用位置
                })
                // res.end('currSize:' + buffers.length +'  '+ (new Date()).toGMTString());//错误的调用位置
                break;
            default:
                // console.log(req.url);
                res.end();
        };
    }
    
    var server  = http.createServer(router);
    server.listen(PORT,function () {
        // body...
        console.log(`the server is linstening on port ${PORT}`);
    })

    效果:

  • 相关阅读:
    ansible变量
    nginx连接php测试
    redis发布订阅
    堡垒机实例以及数据库操作
    nginx简介,使用
    protobuf
    go NSQ
    go mod
    GIT版本管理工具教程
    linux命令查询网站
  • 原文地址:https://www.cnblogs.com/qcblog/p/7142660.html
Copyright © 2011-2022 走看看