zoukankan      html  css  js  c++  java
  • html5文件上传断点续传

    最近公司要做一个html5上传的jquery插件,要在下先实现功能,要求显示上传进度,文件信息,断点续传等等。我一看,艾玛!Σ(゚д゚lll),没做过啊。没办法,(# ゚Д゚),只能去查资料了。
    作为一名还未毕业的大学僧,本人表示亚历山大。不过还好是做出来了,不敢说代码写得很好,大家将就着看吧。
    感谢以下文章提供的思考方向:
    http://www.script-tutorials.com/pure-html5-file-upload/
    http://fex.baidu.com/blog/2014/04/html5-uploader/

    由于传的时候不小心,文件弄错了,现在bug已修复,对不起啊大家
    考虑到服务器原因现在停止上传演示页面,抱歉请大家谅解
    演示地址:暂停
    资源地址:我是下载地址

    HTML:

    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
    <title>upload html5</title>
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <link rel="stylesheet" type="text/css" href="css/upload.css">
    </head>
    <body ontouchmove="event.preventDefault()">
    <div id="upload_box">
        <form id="upload_form" name="upload_form" action="javascript:init();" method="post" enctype="multipart/form-data">
            <div><label for="file">Please select file</label></div>
            <div><input type="file" id="file" name="file" onchange="fileReady()"><div>
            <input type="submit" id="submit" name="submit" value="上传">
            <button id="clear" onclick="clearUploadFile()">清除</button>
            <div class="upload_message_show">
                <!--进度条-->
                <div class="upload_bar_box">
                    <div class="upload_bar"></div>
                    <span class="upload_percent"></span>
                </div>
                <!--上传剩余时间和上传速度-->
                <div class="upload_count">
                    <div class="left_time">剩余时间 | 00:00:00</div>
                    <div class="speed">100k/s</div>
                </div>
                <!--文件信息-->
                <div class="upload_file_message">
                    <div class="message_box">
                        <div class="upload_file_name"></div>
                        <div class="upload_file_size"></div>
                        <div class="upload_file_type"></div>
                        <div class="upload_file_error"></div>
                        <div class="isCompleted"></div>
                    </div>
                    <!--文件预览-->
                    <div class="upload_file_preview"></div>
                </div>
            </div>
        </div>
    <script type="text/javascript" src="js/html5_upload_ano.js"></script>
    </body>
    </html>

    CSS:

    style.css

    /*************reset****************/
    html{color:#333;-webkit-text-size-adjust:none;height:100%;max-height:100%;overflow: hidden;font-family: 'Microsoft Yahei';}
    body{height: 100%;max-height:100%;overflow: hidden;}
    body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}
    table{border-collapse:collapse;border-spacing:0;}
    fieldset,img{border:0;}
    address,caption,cite,code,dfn,em,var,optgroup{font-style:inherit;font-weight:inherit;}
    del,ins{text-decoration:none;}
    li{list-style:none;}
    h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}
    abbr,acronym{border:0;font-variant:normal;}
    sup{vertical-align:baseline;}
    sub{vertical-align:baseline;}legend{color:#000;}
    input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
    body{font-size:12px;}
    a{color: #333333;text-decoration: none;}
    a:hover{text-decoration:underline; color:#c00;}
    
    /*font*/
    *{
        font-size: 1.05em;
        color: #222;
        font-family: "Microsoft Yahei";
    }

    upload.css

    #upload_box{
        padding:0em 1em;
        padding-top:20px;
        height:100%;
        background: #74b1d1;
        position: relative;
    }
    
    #upload_form{
        background: #fff;
        height: 80%;
        padding: 1.4em 1em;
        border-radius: 4px;
        box-shadow: 0 1px 3px rgba(0,0,0,0.7);
    }
    
    #upload_form label{
        font-size: 1.5em;
        font-weight: bolder;
    }
    
    #file{
        margin:20px 0;
        border:1px solid #ccc;
        border-radius: 5px;
        padding: 0.5em;
        font-size: 1.4em;
         90%;
    }
    
    #submit,#clear{
        font-size:1.2em;
        padding:0.3em 1.2em;
        border-radius:10px;
        border:1px solid #d9d9d9;
        background: -webkit-linear-gradient(#ffffff,#dfdfdf);
        background: -o-linear-gradient(#ffffff,#dfdfdf);
        background: -moz-linear-gradient(#ffffff,#dfdfdf);
        background: linear-gradient(#ffffff,#dfdfdf);
        box-shadow:0px 1px 3px rgba(0,0,0,0.7);
        outline: none;
    }
    
    #submit{
        margin-right:1.6em;
    }
    
    #submit:hover,#clear:hover{
        background: -webkit-linear-gradient(#66ccff,#74b1d1);
        background: -o-linear-gradient(#66ccff,#74b1d1);
        background: -moz-linear-gradient(#66ccff,#74b1d1);
        background: linear-gradient(#66ccff,#74b1d1);
        cursor: pointer;
    }
    
    .upload_message_show{
        margin-top: 20px;
        display: none;
    }
    
    .upload_file_message{
        padding: 1.4em 0em;
        padding-left: 60%;
        padding-right: 1.2em;
        border-radius: 10px;
        background: -webkit-linear-gradient(#dfdfdf,#cccccc);
        background: -o-linear-gradient(#dfdfdf,#cccccc);
        background: -moz-linear-gradient(#dfdfdf,#cccccc);
        background: linear-gradient(#dfdfdf,#cccccc);
        font-size: 1.1em;
        font-weight: bolder;
        position: relative;
        min-height: 6.5em;
    }
    
    .upload_file_error{
        color:red;
    }
    
    .message_box{
        position: absolute;
        left: 1.2em;
        top: 1.4em;
    }
    
    .upload_file_preview{
        height: 100%;
        position: relative;
    }
    
    .upload_bar_box{
         100%;
        height: 1em;
        border-radius:0.5em;
        position: relative;
        box-shadow:0px 0px 3px rgba(0,0,0,0.6);
        line-height: 1em;
    }
    
    .upload_bar{
        0%;
        border-radius:0.5em;
        background:-webkit-linear-gradient(#F01731,#F50B43);
        background:-o-linear-gradient(#F01731,#F50B43);
        background:-moz-linear-gradient(#F01731,#F50B43);
        background:linear-gradient(#F01731,#F50B43);
        height:100%;
    }
    
    .upload_percent{
        position: absolute;
        right: 10px;
        top:0em;
        font-weight:700;
    }
    
    .upload_count{
         100%;
        font-size:0.8em;
        margin-top:1em;
        position: relative;
    }
    
    .left_time{
        margin-left: 1em;
    }
    
    .speed{
        position: absolute;
        right:1em;
        top: 0em;
    }

    js:

    变量定义:

    var nSlice_count = 100,//分段数,文件分段数
        nFactCount,           //实际分段数
        nMin_size      = 0.5,//最小分段大小(M)
        nMax_size     = 5,  //最大分段大小(M)
        nFactSize,           //实际分段大小
        nCountNum     = 0,  //分段标号
        sFile_type,           //文件类型
        nFile_load_size,   //文件上传部分大小
        nFile_size,           //文件大小
        nPreuploaded = 0,  //上一次记录上传部分的大小
        bIs_uploading= false,//是否上传中
        bStart_upload= false,//是否开始上传
        bEnd_upload  = false;//是否上传完成

    当文件域变化或者点击清空时,重置所有已记录信息:

    function messageChange(){
        document.querySelector(".upload_file_name").innerHTML ="文件名称: " ;
        document.querySelector(".upload_file_type").innerHTML ="文件类型: " ;
        document.querySelector(".upload_file_size").innerHTML ="文件大小: " ;
        document.querySelector(".isCompleted").innerHTML       ="上传状态: " ;
        document.querySelector(".upload_bar").style.width = "0%";
        document.querySelector(".upload_percent").innerHTML = "0%";
        document.querySelector(".upload_file_preview").innerHTML ="";
        document.querySelector(".upload_message_show").style.display = "none";
    }
    
    function clearUploadFile(e){
        var e = e || event;
        e.stopPropagation();
        e.preventDefault();
        document.getElementById("file").value = "";
        bStart_upload = false;
        messageChange();
    }
    
    
    function fileReady(){
        bIs_uploading = false;
        bEnd_upload = false;
        nCountNum = 0;
        bStart_upload = false;
        messageChange();
    }

    发生错误时的处理:

    function errorUp(){
        bStart_upload = false;
        document.querySelector(".upload_file_error").innerHTML = "上传过程中出错";
    }
    
    function abortUp(){
        bStart_upload = false;
        document.querySelector(".upload_file_error").innerHTML = "网络故障,请检查重试";
    }

    文件上传后提供预览,考虑到手机小屏幕的问题,只在ipad和pc上提供预览,预览的文件类型为
    image/video/audio,由于浏览器对多媒体格式的支持不同,不能保证每个文件都能正常播放

    function filePreview($src){
        var ftype = sFile_type;
        var $temp;
        var IMGMaxHeight = document.querySelector(".upload_message_show").offsetHeight;
        switch(ftype){
            case "image" :
            $temp = '<img src="source/'+$src.url+'" style="max-height:'+IMGMaxHeight+'px;margin-left:30%;">';
            break;
            case "audio" :
            $temp = '<audio src="source/'+$src.url+'" controls="controls"></audio>';
            break;
            case "video" :
            $temp = '<video src="source/'+$src.url+'" controls="controls"></video>';
            break;
        }
        var IsPreview = checkUserAgent();
    
        if(IsPreview)
        document.querySelector(".upload_file_preview").innerHTML = $temp;
    }
    
    function checkUserAgent(){
        var msg = true;
        var agent = ["ipod","iphone","android","symbian","windows mobile"];
        var info =navigator.userAgent.toLowerCase();
        
        for(var i=0,j=agent.length;i<j;i++)
        {
            if(info.indexOf(agent[i])>0)
            msg = false;
        }
    
        return msg;
    }

    数据单位转化:

    var conversion = (function(){
            var unitConversion = {
                bytesTosize:function(data){
                    var unit = ["Bytes","KB","MB","GB"];
                    var i = parseInt(Math.log(data)/Math.log(1024));
                    return (data/Math.pow(1024,i)).toFixed(1) + " " + unit[i];
                },
                secondsTotime:function(sec){
                    var h = Math.floor(sec/3600),
                        m = Math.floor((sec-h*3600)/60),
                        s = Math.floor(sec-h*3600-m*60);
                    if(h<10) h = "0" + h;
                    if(m<10) m = "0" + m;
                    if(s<10) s = "0" + s;
    
                    return h + ":" + m + ":" + s + ":";
                }
            };
    
            return unitConversion;
        })();

    文件上传和上传时的计算:

    //start sending
        var reader = new FileReader();
        var timer;
    
        var fProgress = function(e){
            var fSize = get_file_message.getAll().fileSize;
            timer = setTimeout(uploadCount(e,fSize,conversion),300);
        };
    
        var floadend = function(e){
            if(reader.error){alert("上传失败,出现未知错误");clearTimeout(timer);return;}
            clearTimeout(timer);
            if(nCountNum+1!=nFactCount)
            {
                if(bStart_upload)
                {
                    nCountNum++;
                    uploadStart();
                    return;
                } else {
                    document.querySelector(".speed").innerHTML = "0k/s";
                    document.querySelector(".left_time").innerHTML = "剩余时间 | 00:00:00";
                    return;
                }        
            }
    
            bEnd_upload = true;
            document.querySelector(".layer_box").style.display = "none";
            document.querySelector(".speed").innerHTML = "0k/s";
            document.querySelector(".left_time").innerHTML = "剩余时间 | 00:00:00";
            document.querySelector(".upload_percent").innerHTML = "100.00%";
            document.getElementById("submit").value = "上传";
            
            var $res = JSON.parse(e.target.responseText);
            filePreview($res);
            if($res.res=="success") bIs_uploading =true;
            document.querySelector(".isCompleted").innerHTML="上传状态: " + (bIs_uploading?"上传完成":"正在上传..");
        };
    
        var uploadStart = function(){
            var get_all = get_file_message.getAll();
            var start = nCountNum * nFactSize,
                end   = Math.min(start+nFactSize,get_all.fileSize);
    
            var fData = new FormData();
    
            fData.append("file",file.slice(start,end));
            fData.append("name",file.name);
            fData.append("size",file.size);
            fData.append("type",file.type);
            fData.append("totalCount",nFactCount);
            fData.append("indexCount",nCountNum);
            fData.append("trueName",file.name.substring(0,file.name.lastIndexOf(".")));
    
            
            document.querySelector(".layer_box").style.display = "block";
            if(!sFile_type)
            sFile_type = file.type.substring(0,file.type.indexOf("/"));
            var xhr = new XMLHttpRequest();
            xhr.upload.addEventListener("progress",fProgress,false);
            xhr.addEventListener("load",floadend,false);
            xhr.addEventListener("error",errorUp,false);
            xhr.addEventListener("abort",abortUp,false);
            
            xhr.open("POST","php/send/");
            xhr.send(fData);
        };
    
        reader.onloadstart = function(){
            var get_all = get_file_message.getAll(),
                fName = get_all.fileName,
                fType = get_all.fileType,
                fSize = conversion.bytesTosize(get_all.fileSize);
    
            document.querySelector(".upload_message_show").style.display = "block";
            document.querySelector(".upload_file_name").innerHTML ="文件名称: " + fName;
            document.querySelector(".upload_file_type").innerHTML ="文件类型: " + fType;
            document.querySelector(".upload_file_size").innerHTML ="文件大小: " + fSize;
            document.querySelector(".isCompleted").innerHTML       ="上传状态: " + (bIs_uploading?"完成":"正在上传中..");
    
            nFactSize = get_all.fileSize/nSlice_count;
            nFactSize = (nFactSize>=nMin_size*1024*1024?nFactSize:nMin_size*1024*1024);
            nFactSize = (nFactSize<=nMax_size*1024*1024?nFactSize:nMax_size*1024*1024);
            nFactCount= Math.ceil(get_all.fileSize/nFactSize);
    
            uploadStart();
        };
    
    
        reader.readAsBinaryString(file);
    }
    
    function uploadCount(e,fSize,conversion){
        var upSize = e.loaded+nCountNum*nFactSize,
            perc = (upSize*100/fSize).toFixed(2) + "%";
        var speed = Math.abs(upSize - nPreuploaded);
        if(speed==0){clearTimeout("timer");return;}
        var leftTime = conversion.secondsTotime(Math.round((fSize-upSize)/speed));
        speed = conversion.bytesTosize(speed)+"/s";
        document.querySelector(".speed").innerHTML = speed;
        document.querySelector(".left_time").innerHTML = "剩余时间 | " + leftTime;
        document.querySelector(".upload_percent").innerHTML = perc;
        document.querySelector(".upload_bar").style.width = perc;
        nPreuploaded = upSize;
    }

    PHP:

    <?php
    
    $fsize = $_POST['size'];
    $findex =$_POST['indexCount'];
    $ftotal =$_POST['totalCount'];
    $ftype = $_POST['type'];
    $fdata = $_FILES['file'];
    $fname = mb_convert_encoding($_POST['name'],"gbk","utf-8");
    $truename = mb_convert_encoding($_POST['trueName'],"gbk","utf-8");
    
    $path = "../../";
    $dir = $path."source/".$truename."-".$fsize;
    $save = $dir."/".$fname;
    if(!is_dir($dir))
    {
        mkdir($dir);
        chmod($dir,0777);
    }
    
    //读取临时文件内容
    $temp = fopen($fdata["tmp_name"],"r+");
    $filedata = fread($temp,filesize($fdata["tmp_name"]));
    //将分段内容存放到新建的临时文件里面
    if(file_exists($dir."/".$findex.".tmp")) unlink($dir."/".$findex.".tmp");
    $tempFile = fopen($dir."/".$findex.".tmp","w+");
    fwrite($tempFile,$filedata);
    fclose($tempFile);
    
    fclose($temp);
    
    if($findex+1==$ftotal)
    {
        if(file_exists($save)) @unlink($save);
        //循环读取临时文件并将其合并置入新文件里面
        for($i=0;$i<$ftotal;$i++)
        {
            $readData = fopen($dir."/".$i.".tmp","r+");
            $writeData = fread($readData,filesize($dir."/".$i.".tmp"));
    
            $newFile = fopen($save,"a+");
            fwrite($newFile,$writeData);
            fclose($newFile);
            
            fclose($readData);
    
            $resu = @unlink($dir."/".$i.".tmp"); 
        }
        $res = array("res"=>"success","url"=>mb_convert_encoding($truename."-".$fsize."/".$fname,'utf-8','gbk'));
        echo json_encode($res);
    }
    
    ?>

    还有一些细节的js这里没给出来,主要就上面的功能,有问题的话欢迎回复,楼主只是个新手,不足之处请大家多多见谅。

  • 相关阅读:
    2015-01-27-从实验出发理解buffer与cache区别-吴伟顺
    【实习记】2014-09-26恢复linux下误删的ntfs盘中的文件
    【实习记】2014-09-24万事达卡bin查询项目总结
    【实习记】2014-09-04浏览代码查middle资料+总结我折腾过的源码浏览器
    【实习记】2014-09-01从复杂到简单:一行命令区间查重+长整型在awk中的bug
    【实习记】2014-08-29算法学习Boyer-Moore和最长公共子串(LCS)
    【实习记】2014-08-28知值求范围问题
    【实习记】2014-08-27堆排序理解总结+使用typedef指代函数指针
    【实习记】2014-08-26都是回车惹的祸——shell脚本必须是unix行尾
    【实习记】2014-08-24实习生无法映射磁盘替代方案rsync+非默认端口22设置
  • 原文地址:https://www.cnblogs.com/10manongit/p/12972572.html
Copyright © 2011-2022 走看看