用jQuery File Upload作的上傳控件demo,支持同頁面多個上傳按鈕

需求

有這麼一個需求,一個form有多個文件要上傳,但又不是傳統的圖片批量上傳那種,是相似下圖這種需求,一開始是用的swfupload作的上傳,可是問題是若是有多個按鈕的話,就要寫不少重複的代碼,於爲了代碼的簡潔因此就開始尋求其餘的方法,期間試過uploadify,可是因爲樣式始終調不出來,最後就放棄了,直到發現這麼個小巧的玩意,jQuery File Upload。javascript

 

本文包含了upload的js實現,html的分析,css的實現等內容,文章末尾有git地址 css

 

最簡運行時

官網下載的demo有N多js文件,一大堆js文件中只有幾個纔是必要的,其餘的文件都是一些用不到的功能,只有在你須要的時候才須要引用。html

    <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下才須要的,最後一個文件是主體java

 

後臺代碼

新建一個ashx的文件,這裏創建一個uploadHandler.ashx,而後寫入以下代碼,用於保存。jquery

    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

預覽效果

最終的效果如上圖所示,爲了實現這個咱們一步一步來分析。git

 

DIV結構

如上圖ajax

  1. 做爲整個控件的最外層
  2. 是按鈕
  3. 是上傳完成後顯示的文件名(上傳開始前隱藏)
  4. 上傳進度百分比(上傳開始前隱藏)
  5. 上傳進度條(上傳開始前隱藏)

 

上圖後4個div按照順序寫在最外層裏面,而後考慮經過浮動來解決位置的問題,固然也能夠用絕對定位等方法來實現,這裏選擇了浮動。json

由於要用到浮動,這裏簡單解釋一下浮動的原理api

首先設置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;
    width:280px;
    height:30px;
}
.upload .uploadbtnBox
{
    float:left;
    height:30px;
    width:70px;
    margin-right:8px;
}
.upload .progress
{
    height:4px;
    line-height:4px;
    *zoom:1;
    background:#fff;
    float:left;
    width:200px;
    border:1px #ccc solid;
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;

    display:none;
}
.upload .filestate
{
    float:left;
    height:20px;
    text-align:left;
    width: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;
    width: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="width: 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

相關文章
相關標籤/搜索