zoukankan      html  css  js  c++  java
  • 用jQuery File Upload做的上传控件demo,支持同页面多个上传按钮

    需求

    有这么一个需求,一个form有多个文件要上传,但又不是传统的图片批量上传那种,是类似下图这种需求,一开始是用的swfupload做的上传,但是问题是如果有多个按钮的话,就要写很多重复的代码,于为了代码的简洁所以就开始寻求其他的方法,期间试过uploadify,但是由于样式始终调不出来,最后就放弃了,直到发现这么个小巧的玩意,jQuery File Upload。

    本文包含了upload的js实现,html的分析,css的实现等内容,文章末尾有git地址

    最简运行时

    官网下载的demo有N多js文件,一大堆js文件中只有几个才是必要的,其他的文件都是一些用不到的功能,只有在你需要的时候才需要引用。

        <script src="http://libs.baidu.com/jquery/1.10.2/jquery.min.js" type="text/javascript"></script>
        <script src="JS/jquery/jquery.iframe-transport.js"></script>
        <script src="JS/jquery/jquery.ui.widget.js"></script>
        <script src="JS/jquery/jquery.xdr-transport.js"></script>
        <script src="JS/jquery/jquery.fileupload.js"></script>

    其中iframe那个文件是为了进行iframe上传,ui文件是能选完文件自动上传的必要文件,xdr那个是在ie下才需要的,最后一个文件是主体

    后台代码

    新建一个ashx的文件,这里建立一个uploadHandler.ashx,然后写入如下代码,用于保存。

        public void ProcessRequest(HttpContext context)
            {
                context.Response.ContentType = "text/plain";
                context.Response.Charset = "utf-8";
    
                HttpPostedFile file = context.Request.Files["files"];
                string uploadPath =
                    HttpContext.Current.Server.MapPath(@context.Request["folder"]) + "\";
    
                if (file != null)
                {
                    if (!Directory.Exists(uploadPath))
                    {
                        Directory.CreateDirectory(uploadPath);
                    }
                    file.SaveAs(uploadPath + file.FileName);
                    //下面这句代码缺少的话,上传成功后上传队列的显示不会自动消失
                    string newName = file.FileName;
                    string oldName = file.FileName;
                    context.Response.Write("{"newName": "" + newName + "", "oldName": "" + oldName + ""}");
                }
                else
                {
                    context.Response.Write("0");
                }
            }

    前台HTML

    预览效果

    最终的效果如上图所示,为了实现这个我们一步一步来分析。

    DIV结构

    如上图

    1. 作为整个控件的最外层
    2. 是按钮
    3. 是上传完成后显示的文件名(上传开始前隐藏)
    4. 上传进度百分比(上传开始前隐藏)
    5. 上传进度条(上传开始前隐藏)

    上图后4个div按照顺序写在最外层里面,然后考虑通过浮动来解决位置的问题,当然也可以用绝对定位等方法来实现,这里选择了浮动。

    因为要用到浮动,这里简单解释一下浮动的原理

    首先设置0的宽度是280px

    所以1的宽度就是70+margin-right:8 右侧还有202宽度,左浮动

    2的宽度是150px,左浮动

    3的宽度不设置,右浮动

    4的宽度是200+border:2 一共202宽度,左浮动

    然后再设置上传按钮,如果不设置样式,上传按钮是这样的

    这样显然是老套的样式了,在网上找了一个解决方案是这样的

    配合这样的样式

    就可以做出这个效果了

    所以html的代码如下:

       <style>
    
    body{padding:10px}
    /* 上传控件 */
    .upload
    {
        margin-top:10px;
        280px;
        height:30px;
    }
    .upload .uploadbtnBox
    {
        float:left;
        height:30px;
        70px;
        margin-right:8px;
    }
    .upload .progress
    {
        height:4px;
        line-height:4px;
        *zoom:1;
        background:#fff;
        float:left;
        200px;
        border:1px #ccc solid;
        overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
    
        display:none;
    }
    .upload .filestate
    {
        float:left;
        height:20px;
        text-align:left;
        150px;
        line-height:20px;
        display:none;
        color:#333;
        overflow:hidden;
    }
    .upload .progresspercent
    {
        float:right;
        padding-top:5px;
        height:15px;
        text-align:right;
        font-size:9px;
        line-height:15px;
        color:#333;
    }
    
    .upload .uploadbtnBox .a-upload {
        height:28px;
        background:#4090c0;
        border:1px solid #dddddd;color:#ffffff;
        line-height:28px;
        padding:0 6px;
        font-size:0.9em;
        overflow: hidden;
        display: inline-block;
        text-decoration:none;
        *display: inline;
        *zoom: 1
    }
    
    .upload .uploadbtnBox .a-upload  input {
        position: absolute;
        70px;
        height:30px;
        overflow:hidden;
        margin-left:-10px;
        opacity: 0;
        filter: alpha(opacity=0);
        cursor: pointer
    }
    
    .upload .progress .bar
    {
        height:4px;
        line-height:4px;
        background:#4090c0;
        *zoom:1; 
    }
    
    .clearfix:after {
        content: ".";
        display: block;
        height: 0;
        visibility: hidden;
        clear: both;
    }
    .clearfix {
        _zoom: 1;
    }
    .clearfix {
    *zoom:1;
    }
    
        </style>
    
    
    <div class="upload clearfix">
            <div class="uploadbtnBox clearfix">
                <a href="javascript:;" class="a-upload">
                    <input type="file" data-url="uploadHandler.ashx" name="files" value="" id="file7"
                        onchange="CheckFile(this)" />点击上传 </a>
            </div>
            <div class="filestate">
                文件名</div>
            <div class="progresspercent">
            </div>
            <div class="progress" style="height: 4px;">
                <div class="bar" style=" 0%;">
                </div>
            </div>
        </div>
    View Code

    JS部分

    基本的upload直接这样就可以了,

    $("input[type=file]").fileupload();

    上传的后台页面通过input的data-url来设置,如下图

    接下来要处理的是上传进度

    通过计算上传的百分比设置bar的宽度就可以了

    这里用到的是内置的progressall的方法,传递2个参数,第一个是e就是sender,通过他找到触发的input,然后再用jquery去找其他的兄弟元素进行操作,这里是找到了progress和bar然后设置他们的宽度

    第二个参数是data,里面包含两个内置的变量,一个是total,一个是loaded,所以就可以计算出百分比了

    上传完成后显示文件名,还有给隐藏input赋值,

    使用的是内置的函数done,done会提供2个参数,第一个是e就是sender,我们通过他找到对应的input,然后找到其他元素进行操作

    另一个参数就是result,在注释里已经说明了result如何使用了

    所以最后的js就是这样

        <script type="text/javascript">
    
            function CheckFile(obj) {
                var array = new Array('gif', 'jpeg', 'png', 'jpg');  //可以上传的文件类型  
                if (obj.value == '') {
                    alert("让选择要上传的图片!");
                    return false;
                }
                else {
                    var fileContentType = obj.value.match(/^(.*)(.)(.{1,8})$/)[3]; //这个文件类型正则很有用:)  
                    var isExists = false;
                    for (var i in array) {
                        if (fileContentType.toLowerCase() == array[i].toLowerCase()) {
                            isExists = true;
                            return true;
                        }
                    }
                    if (isExists == false) {
                        obj.value = null;
                        alert("上传图片类型不正确!");
                        return false;
                    }
                    return false;
                }
            }
            $(function () {
                $("input[type=file]").fileupload({
                    done: function (e, result) {
                        //done方法就是上传完毕的回调函数,其他回调函数可以自行查看api
                        //注意result要和jquery的ajax的data参数区分,这个对象包含了整个请求信息
                        //返回的数据在result.result中,假设我们服务器返回了一个json对象
                //但是由于IE10以下存在bug,会将XHR的内容识别错误,所以第一需要返回Content-Type: text/plain
                //其次,及时转成text/plain还存在取不到result.result的内容,取到的是其他的东西
                //需要用这个方法来接值,var jmsg = result.result[0].body ? result.result[0].body.innerHTML : result.result;
                //最后接到值后,发现还有<pre></pre>包着需要通过字符串处理去掉这个东西
    //json对象{"newName": "sss", "oldName": "sdf"}

    var resultJson;
    var jmsg = result.result[0].body ? result.result[0].body.innerHTML : result.result;
    var startIndex = jmsg.indexOf("{");
    var lastIndex = jmsg.lastIndexOf("}");
    jmsg = jmsg.substring(startIndex, lastIndex+1);
    try { resultJson = $.parseJSON(jmsg); }
    catch (e) { resultJson = jmsg; }
    var uploadDiv = $(e.target).parent().parent().parent();
    uploadDiv.find(".filehidden").val(resultJson.newName);
    uploadDiv.find(".filestate").show().text(resultJson.oldName);

    
                    },
                    progressall: function (e, data) {
                        var maxWidth = 200;
                        var percent = (data.loaded / data.total * 100).toFixed(2);
                        var progress = parseInt(data.loaded / data.total * maxWidth, 10);
                        var uploadDiv = $(e.target).parent().parent().parent();
                        uploadDiv.find(".progress").show();
                        uploadDiv.find(".bar").css("width", progress);
                        uploadDiv.find(".progresspercent").show().text(percent + "%");
    
                    }
                })
            });
        
        </script>

    ps:

    但是由于IE10以下存在bug,会将XHR的内容识别错误,所以第一需要返回Content-Type: text/plain
    其次,及时转成text/plain还存在取不到result.result的内容,取到的是其他的东西
    需要用这个方法来接值,var jmsg = result.result[0].body ? result.result[0].body.innerHTML : result.result;
    最后接到值后,发现还有<pre></pre>包着需要通过字符串处理去掉这个东西

    git地址:https://git.oschina.net/jangojing/jqueryfileuploadDemo.git

  • 相关阅读:
    socket的双重属性
    Client/Server 模型 与socket
    简单理解Socket 重要
    C++ 异常处理机制的实现
    ARM汇编之MOV指令
    指令集 与 cpu
    寄存器简介 与 ebp esp
    ESP和EBP 栈顶指针和栈底指针
    函数调用过程栈帧变化详解
    栈帧
  • 原文地址:https://www.cnblogs.com/JangoJing/p/4767525.html
Copyright © 2011-2022 走看看