文件上传进度检测/拖拽上传的处理(读取文件内容)

文件上传进度检测

    //AJAX2.0中AJAX对象有进度上传的监听事件(upload)
    //upload中有onprogress事件 
    //1.该事件必须放到AJAX创建后send()之前的位置,否则upload事件不会响应
    //2.使用此事件时,express必须使用server.use接收数据,设置跨域.
    //  原因是此时发送数据会产生两次请求POST与OPTIONS,使用USE才可以接收所有的请求
    ajax.upload.onprogress = function(ev){
        ev.loaded //表示完成了多少上传进度
        ev.total //表示总共有多少
        ev.loaded/ev.total  //=>得出0~1之间的数,代表进度
    }
    //注意事项
    ajax.onprogress 显示的是下载的进度
    ajax.upload.onprogress 显示的是上传的进度

拖拽上传的处理(读取文件内容)

    //使用FileReader读取上传的文件
    let reader = new FileReader();
    //参数file是 拖动松手事件后返回ev..dataTransfer.files;参考2-6 119行
    readAsText(file)//读取文本文件
    readAsDataURL(file)//读取二进制的文件,以base64编码形式存储数据
    readAsBinaryString(file) //以字符串形式存储的二进制数据
    readAsArrayBuffer(file) //以二进制数据的形式存储数据,可以转换成Blob。
    reader.onload = function(){//通常把onload函数写在读取文件之前,防止文件读取太快,出现onload触发不了的BUG
        reader.result//获得上述四个方法读取文件内容的结果
    }
    //核心代码如下
    //拖住DIV的拖拽松手事件
    oBox.addEventListener('drop', (ev)=>{
    //循环长传的files操作
    Array.from(ev.dataTransfer.files).forEach(file=>{
        //判断如果该文件不是图片就取消本次操作
        if(!file.type.startsWith('image/')){
        return;
        }
        //创建文件读取对象
        let reader=new FileReader();
        //文件读取完毕事件
        reader.onload=function (){
        let oLi=document.createElement('li');
        oLi.file=file;//将file保存在li中,方便以后存库使用
        oLi.innerHTML='<img src="a.png" alt=""><a href="javascript:;" class="del_btn">删除</a>';

        let oImg=oLi.children[0];
        oImg.src=this.result;//图片地址指向文件读取结果,此处是base64
        //删除
        let oBtnDel=oLi.children[1];
        oBtnDel.onclick=function (){
            oUl.removeChild(oLi);
        };

        oUl.appendChild(oLi);
        };
        //文件读取,写在后面防止onload事件不被触发
        reader.readAsDataURL(file);
    });
    //阻止默认事件
    ev.preventDefault();
    }, false);

    //真的上传,点击上传后使用formdata上传
    let oBtnUpload=document.querySelector('#btn_upload');
    oBtnUpload.onclick=function (){
    let data=new FormData();//创建formdata对象

    Array.from(oUl.children).forEach(li=>{
        data.append('f1', li.file);//循环放入data中
    });

    //
    let oAjax=new XMLHttpRequest();//创建ajax

    //POST
    oAjax.open('POST', `http://localhost:8080/api`, true);
    oAjax.send(data);//发送数据

    oAjax.onreadystatechange=function (){
        if(oAjax.readyState==4){
        if(oAjax.status>=200 && oAjax.status<300 || oAjax.status==304){
            alert('成功');
        }else{
            alert('失败');
        }
        }
    };
    };

    //服务端代码如下 注释参考2-6;
    const express=require('express');     //主体
    const body=require('body-parser');    //接收普通POST数据
    const multer=require('multer');       //接收文件POST数据
    const mysql=require('mysql');         //数据库
    //连接数据库
    let db=mysql.createPool({host: 'localhost', port: 3309, user: 'root', password: '', database: '20180208'});
    //监听
    let server=express();
    server.listen(8080);

    //中间件
    server.use(body.urlencoded({extended: false}));

    let multerObj=multer({dest: './upload/'});
    server.use(multerObj.any());

    //处理请求
    server.use('/api', (req, res)=>{
        //处理跨域
        if(req.headers['origin']=='null' || req.headers['origin'].startsWith('http://localhost')){
            res.setHeader('Access-Control-Allow-Origin', '*');
        }

        let arr=[];
        req.files.forEach(file=>{
            arr.push(`('${file.originalname}', '${file.filename}', ${Math.floor(Date.now()/1000)})`);
        });

        let sql=`INSERT INTO image_table (originalname, filename, time) VALUES${arr.join(',')}`;

        db.query(sql, (err)=>{
            if(err){
            res.send('不OK');
            }else{
            res.send("OK");
            }
        });
    });
    server.use(express.static('./www/'));

扩展

服务器中有多个IP时,指定服务器监听IP
    server.listen中除了端口,还可以有参数指定IP,如果没有指定iP就是默认IP.

meter标签(H5新增的进度条标签)//可以使用css调整样式
    <meter value='0~100进度值' min='0' max='100'>

断点续传
    断点续传普通HTML做不到,通常需要客户端实现.

AJAX版本判断
    高级浏览器支持2.0.有ajax.upload的浏览器就是支持2.0

事件绑定取消默认事件
    直接事件绑定取消默认事件 需要return false;
    使用addEventListener 绑定的事件,取消默认事件需要使用ev.preventDefault();

关于base64
    服务器与浏览器之间传输数据的时候直接传输二进制,
    base64可以把二进制数据转换成字符串

Chrome模拟网速
    控制台 settings 中 Throttling 可以添加模拟网速,添加完成之后在NetWork中Online后选择;
Chrome查看loaclStorage、cookie在控制台Applocation中
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容