Web實戰之文件上傳


前言

因爲討厭各類上傳插件和UI綁定,一樣是爲了本身練練手,我寫了一個十分小巧的jQuery上傳插件——JFilehtml

文檔連接

提供的功能

  • 多文件上傳
  • 中途取消
  • 文件大小、類型限制設定
  • 能取到進度(進度條UI能夠本身定製哦)
  • 可選的上傳圖片預覽
  • 相似於jQuery AJAX的調用風格

依賴

  • 上傳依賴於FormData和Level2的XHttpRequest(通常都支持)
  • 預覽依賴於HTML5的File API
  • jQuery

使用

var jq=$('#input').upload(url,{
    preview:true,
    limits:{
        fieldSize:40,
        ...
    },
    ...
}).done(function(data,status,xhr){..})
  .fail(function(xhr,status,err){..})
  .always(function(xhr,status,err){..})
  .progress(function(percentage){..});
jq.abort();

源代碼

/**
 * Created by suemi on 14-12-8.
 */
(function($){
    $.fn.upload=function(url,settings){

        var option={
            method:'POST',
            action:url,
            dataType:'json',
            limits:{},
            preview:null
        };
        if(!settings) var settings={};
        $.extend(option,settings);
        var getXhr = function(){
            var xhr;
            return function(){
                if (xhr) return xhr;
                if (typeof XMLHttpRequest !== 'undefined') {
                    xhr = new XMLHttpRequest();
                } else {
                    var v = [
                        "Microsoft.XmlHttp",
                        "MSXML2.XmlHttp.5.0",
                        "MSXML2.XmlHttp.4.0",
                        "MSXML2.XmlHttp.3.0",
                        "MSXML2.XmlHttp.2.0"
                    ];
                    for (var i=0; i < v.length; i++){
                        try {
                            xhr = new ActiveXObject(v[i]);
                            break;
                        } catch (e){}
                    }
                }
                return xhr;
            }
        }();
        function checkExtension(dst,src){
            var tmp=dst.split('/');
            if(tmp[0]=='image'){
                if($.inArray('image/*',src)==-1){
                    if($.inArray(tmp[1],src)==-1) return false;
                    else return true;
                }
                else return true;
            }
            else{
                if($.inArray(tmp[1],src)==-1) return false;
                else return true;
            }
        }




        var fileList=[];
        $(this).each(function(){
            for(var i=0;i<this.files.length;i++){
                fileList.push(this.files[i]);
            }
        });
        return $.Deferred(function(){
            var xhr=getXhr();
            var defer=this;
            this.abort=function(){
              if(xhr) xhr.abort();
              return defer;
            };
            this.preview=function(tmp){
                for(var i in fileList){
                    var file=fileList[i];
                    if(file.type.split('/')[0]=='image'){
                        if(!window.FileReader){
                            alert('Too old browser, you need a modern one!');
                            return defer;
                        }
                        var reader=new FileReader();
                        reader.name=file.name;
                        reader.onloadend=function(evt){
                            console.log(this.num);
                            if(reader.error) tmp.append($('<p>'+this.name+' fails to be loaded</p>'));

                            else tmp.append($('<img>',{'src':evt.target.result,'alt':this.name}));
                        };
                        reader.readAsDataURL(file);
                    }
                    else continue;
                }
                return defer;
            };
            if(window.FormData) var form=new FormData();
            else{
                // alert('Too old for your browser, get a modern one!');
                this.reject(xhr,null,new Error('Too Old Browser'));
                return this;
            }
            if(!xhr){
                this.reject(xhr,null,new Error('Too Old Browser'));
                return this;
            }
            if(!option.action){
                this.reject(xhr,null,new Error('URL Needed'));
                return this;
            }
            xhr.open(option.method,option.action);
            xhr.upload.addEventListener('progress',function(evt){
                if(evt.lengthComputable){
                    var complete=evt.loaded/evt.total | 0;
                }
                defer.notify(complete);
            });

            xhr.onreadystatechange=function(){
                if(this.readyState!==4) return;
                if(this.status==200){
                    var data;
                    switch(option.dataType){
                        case 'text':
                            data=this.responseText;
                            break;
                        case 'html':
                            data= $.parseHTML(this.responseText);
                            break;
                        case 'xml':
                            data= $.parseXML(this.responseXML);
                            break;
                        case 'json':
                            data= $.parseJSON(this.responseText);
                            break;
                        default :break;
                    }
                    defer.resolve(data,this.status,this);
                }
                else{
                    defer.reject(this,this.status,this.responseText);
                }
            };
            if(fileList.length==0){
                //defer.reject(xhr,xhr.status,new Error('No File Select'));
                return defer;
            }
            if(option.limits.fieldSize&&option.limits.fieldSize<fileList.length){
                var err=new Error('Too Many Files');
                defer.reject(xhr,xhr.status,err);
                return defer;
            }
            for(var i in fileList){
                var file=fileList[i];
                if(option.limits.validExtension&&!checkExtension(file.type,option.limits.validExtension)){
                    var err=new Error('File Type Error');
                    err.filename=file.name;
                    defer.reject(xhr,xhr.status,err);
                    continue;
                }
                if(option.limits.fileSize&&option.limits.fileSize<file.size){
                    var err=new Error('Too Large Size');
                    defer.reject(xhr,xhr.status,err);
                    return defer;
                }

                if(option.start) option.start(file);
                form.append(i,file,file.name);
                if(option.maxSize) option.maxSize-=file.size;
            }
            if(option.preview) this.preview(option.preview);
            xhr.send(form);
            return defer;
        });
    };
})(jQuery);
相關文章
相關標籤/搜索