1. 程式人生 > >適用於各瀏覽器支援圖片預覽,無重新整理非同步批量上傳js外掛

適用於各瀏覽器支援圖片預覽,無重新整理非同步批量上傳js外掛

注:在下一篇文章中,已經對這個外掛做了更好的優化,如有需要的童鞋可以看下一篇

檔案上傳無疑是web應用中一個非常常用的功能,不管是PHP、jsp還是aspx、mvc等都會需要檔案上傳,但是眾所周知當使用自帶的檔案上傳功能時總會出現頁面重新整理的情況。當然現在有了html5這個好東西,我們可以呼叫它的新的api來做檔案的非同步上傳。但是非常可惜,這個新的api並非每個瀏覽器都支援。



如果你會flash這當然很好,你可以自己寫一個flash的上傳外掛來支援上傳,不過本文不會對flash這個技術做任何的討論。


好了言歸正傳,我們還是來討論下只使用js的情況下如何才能非同步無重新整理的上傳檔案,首先估計大家會想到ajax,不過很不幸在目前沒有html5支援的瀏覽器中使用ajax上傳檔案是不行的,而在國內使用支援html5瀏覽器的使用者還不是絕大多數,那麼這種方案只能放棄。


還有沒有辦法喃?當然有那就是使用iframe,看下面的html程式碼:
<body>
    <form action="WebForm1.aspx" target="dynamic_creation_upload_iframe" method="POST" enctype="multipart/form-data">
    <input type="file" name="upload1" />
    </form>
    <iframe name="dynamic_creation_upload_iframe"></iframe>
</body>
這是一段我們經常使用的上傳程式碼,如果你使用的是asp.net控制元件,它最終也會生成這樣的html程式碼,其中的enctype就是指定需要上傳檔案的屬性(action和method屬性就不需要解釋了吧)。不過在這個form上我添加了一個target屬性,並且指定了它的值為下面那個iframe的name屬性的值,這是為什麼?其實很簡單,就是當你提交這個form時(這樣就開始了檔案上傳),等服務端接收到檔案並儲存成功響應客戶端時,將響應的內容直接在這個iframe中重新整理,這樣這個iframe就起到了一個隔離的作用,此時我們只需要在這個iframe上繫結一個onload事件,那麼當它重新整理時這個事件將被觸發,呵呵 我們就可以在這個load事件中做事情了(例如:在load的時候獲取服務端響應的結果,從而得知上傳是否成功)


有了這個思路事情就好辦了,以下是根據這種思路構建的一個js外掛

/*
    無重新整理非同步上傳外掛
    2013-10-16 Devotion Created
*/
(function ($) {
    var defaultSettings = {
        url: "",                                 //上傳地址
        buttonFeature: true,                    //true:點選按鈕時僅選擇檔案; false:選擇完檔案後立即上傳
        fileSuffixs: ["jpg", "png"],             //允許上傳的檔案字尾名列表
        errorText: "不能上傳字尾為 {0} 的檔案!", //錯誤提示文字,其中{0}將會被上傳檔案的字尾名替換
        onCheckUpload: function (text) { //上傳時檢查檔案字尾名不包含在fileSuffixs屬性中時觸發的回撥函式,(text為錯誤提示文字)
            alert(text);
        },
        onComplete: function (msg) { //上傳完成後的回撥函式[不管成功或失敗,它都將被觸發](msg為服務端的返回字串)
        },


        onChosen: function (file, obj) { //選擇檔案後的回撥函式,(file為選中檔案的本地路徑;obj為當前的上傳控制元件例項)
            //alert(file);
        },
        maximumFilesUpload: 5,//最大檔案上傳數(當此屬性大於1時,buttonFeature屬性只能為true)
        onSubmitHandle: function (uploadFileNumber) { //提交上傳時的回撥函式,uploadFileNumber為當前上傳的檔案數量
            //在此回撥中返回false上傳提交將被阻止
            return true;
        },
        onSameFilesHandle: function (file) { //當重複選擇相同的檔案時觸發
            //在此回撥中返回false當前選擇的檔案將從上傳佇列中取消
            return true;
        },
        perviewImageElementId: "",//用於預覽上傳圖片的元素id(請傳入一個div元素的id)


        perviewImgStyle: null//用於設定圖片預覽時的樣式(可不設定,在不設定的情況下多檔案上傳時只能顯示一張圖片),如{ width: '100px', height: '100px', border: '1px solid #ebebeb' }
    };


    $.fn.uploadFile = function (settings) {


        settings = $.extend({}, defaultSettings, settings || {});


        if (settings.perviewImageElementId) {
            //設定圖片預覽元素的必須樣式
            if (!settings.perviewImgStyle) {
                var perviewImg = document.getElementById(settings.perviewImageElementId);
                perviewImg.style.overflow = "hidden";
            }
        }


        return this.each(function () {
            var self = $(this);


            var upload = new UploadAssist(settings);


            upload.createIframe(this);


            //綁定當前按鈕點選事件
            self.bind("click", function (e) {
                upload.chooseFile();
            });


            //將上傳輔助類的例項,存放到當前物件中,方便外部獲取
            self.data("uploadFileData", upload);


            //建立的iframe中的那個iframe,它的事件需要延遲繫結
            window.setTimeout(function () {


                //為建立的iframe內部的iframe繫結load事件
                $(upload.getIframeContentDocument().body.lastChild).on("load", function () {
                    var dcmt = upload.getInsideIframeContentDocument();
                    if (dcmt.body.innerHTML) {


                        if (settings.onComplete) {
                            settings.onComplete(dcmt.body.innerHTML);
                        }


                        dcmt.body.innerHTML = "";
                    }
                });
            }, 100);
        });
    };
})(jQuery);


//上傳輔助類
function UploadAssist(settings) {
    //儲存設定
    this.settings = settings;
    //已選擇檔案的路徑集合
    this.choseFilePath = [];
    //建立的iframe唯一名稱
    this.iframeName = "upload" + this.getInputFileName();
    return this;
}


UploadAssist.prototype = {
    //輔助類構造器
    constructor: UploadAssist,


    //建立iframe
    createIframe: function (/*外掛中指定的dom物件*/elem) {


        var html = "<html>"
                + "<head>"
                + "<title>upload</title>"
                + "<script>"
                + "function getDCMT(){return window.frames['dynamic_creation_upload_iframe'].document;}"
                + "</" + "script>"
                + "</head>"
                + "<body>"
                + "<form method='post' target='dynamic_creation_upload_iframe' enctype='multipart/form-data' action='" + this.settings.url + "'>"
                + "</form>"
                + "<iframe name='dynamic_creation_upload_iframe'></iframe>"
                + "</body>"
                + "</html>";


        this.iframe = $("<iframe name='" + this.iframeName + "'></iframe>")[0];
        this.iframe.style.width = "0px";
        this.iframe.style.height = "0px";
        this.iframe.style.border = "0px solid #fff";
        this.iframe.style.margin = "0px";
        elem.parentNode.insertBefore(this.iframe, elem);
        var iframeDocument = this.getIframeContentDocument();
        iframeDocument.write(html);
    },


    //獲取上傳控制元件名稱
    getInputFileName: function () {
        return (new Date()).valueOf();
    },


    //建立上傳控制元件到建立的iframe中
    createInputFile: function () {
        var that = this;
        var dcmt = this.getIframeContentDocument();
        var input = dcmt.createElement("input");
        input.type = "file";
        input.setAttribute("name", "input" + this.getInputFileName());
        input.onchange = function () {


            var fileSuf = this.value.substring(this.value.lastIndexOf(".") + 1);


            //檢查是否為允許上傳的檔案
            if (!that.checkFileIsUpload(fileSuf, that.settings.fileSuffixs)) {
                that.settings.onCheckUpload(that.settings.errorText.replace("{0}", fileSuf));
                return;
            }


            //選中後的回撥
            that.settings.onChosen(this.value, this);




            if (that.checkFileIsExist(this.value)) {
                //儲存已經選擇的檔案路徑
                that.choseFilePath.push({ "name": this.name, "value": this.value });
                var status = that.settings.onSameFilesHandle(this.value);
                if (typeof status === "boolean" && !status) {
                    that.removeFile(this.value);
                    return;
                }
            } else {
                //儲存已經選擇的檔案路徑
                that.choseFilePath.push({ "name": this.name, "value": this.value });
            }


            //是否開啟了圖片預覽
            if (that.settings.perviewImageElementId) {
                if (!that.settings.perviewImgStyle) {
                    perviewImage.beginPerview(this, that.settings.perviewImageElementId);
                } else {
                    var ul = perviewImage.getPerviewRegion(that.settings.perviewImageElementId);
                    var main = perviewImage.createPreviewElement(this.value);
                    var li = document.createElement("li");
                    //li.style.float = "left";
                    if ($.browser.msie) {
                        li.style.styleFloat = "left";
                    }
                    else {
                        li.style.cssFloat = "left";
                    }


                    li.style.margin = "5px";
                    li.appendChild(main);
                    ul.appendChild(li);
                    var div = $(main).children("div").get(0);
                    $(main).children("img").hover(function () {
                        this.src = perviewImage.closeImg.after;
                    }, function () {
                        this.src = perviewImage.closeImg.before;
                    }).click(function () {
                        that.removeFile($(this).attr("filepath"));
                        $(this).parents("li").remove("li");
                    });
                    perviewImage.beginPerview(this, div, dcmt);
                }
            }


            if (!that.settings.buttonFeature) {
                that.submitUpload();
            }
        };
        dcmt.forms[0].appendChild(input);
        return input;
    },


    //獲取建立的iframe中的document物件
    getIframeContentDocument: function () {
        return this.iframe.contentDocument || this.iframe.contentWindow.document;
    },


    //獲取建立的iframe所在的window物件
    getIframeWindow: function () {
        return this.iframe.contentWindow || this.iframe.contentDocument.parentWindow;
    },


    //獲取建立的iframe內部iframe的document物件
    getInsideIframeContentDocument: function () {
        return this.getIframeWindow().getDCMT();
    },


    //獲取上傳input控制元件
    getUploadInput: function () {
        var inputs = this.getIframeContentDocument().getElementsByTagName("input");
        var len = inputs.length;


        if (len > 0) {
            if (!inputs[len - 1].value) {
                return inputs[len - 1];
            } else {
                return this.createInputFile();
            }
        }
        return this.createInputFile();
    },


    //forEach迭代函式
    forEach: function (/*陣列*/arr, /*代理函式*/fn) {
        var len = arr.length;
        for (var i = 0; i < len; i++) {
            var tmp = arr[i];
            if (fn.call(tmp, i, tmp) == false) {
                break;
            }
        }
    },


    //提交上傳
    submitUpload: function () {
        var status = this.settings.onSubmitHandle(this.choseFilePath.length);
        if (typeof status === "boolean") {
            if (!status) {
                return;
            }
        }
        this.clearedNotChooseFile();
        var dcmt = this.getIframeContentDocument();
        dcmt.forms[0].submit();
    },


    //檢查檔案是否可以上傳
    checkFileIsUpload: function (fileSuf, suffixs) {


        var status = false;
        this.forEach(suffixs, function (i, n) {
            if (fileSuf.toLowerCase() === n.toLowerCase()) {
                status = true;
                return false;
            }
        });
        return status;
    },


    //檢查上傳的檔案是否已經存在上傳佇列中
    checkFileIsExist: function (/*當前上傳的檔案*/file) {


        var status = false;
        this.forEach(this.choseFilePath, function (i, n) {
            if (n.value == file) {
                status = true;
                return false;
            }
        });
        return status;
    },


    //清除未選擇檔案的上傳控制元件
    clearedNotChooseFile: function () {
        var files = this.getIframeContentDocument().getElementsByTagName("input");


        this.forEach(files, function (i, n) {
            if (!n.value) {
                n.parentNode.removeChild(n);
                return false;
            }
        });
    },


    //將指定上傳的檔案從上傳佇列中刪除
    removeFile: function (file) {
        var that = this;
        var files = this.getIframeContentDocument().getElementsByTagName("input");
        this.forEach(this.choseFilePath, function (i, n) {
            if (n.value == file) {
                that.forEach(files, function (j, m) {
                    if (m.name == n.name) {
                        m.parentNode.removeChild(m);
                        return false;
                    }
                });
                that.choseFilePath.splice(i, 1);
                return false;
            }
        });
    },


    //清空上傳佇列
    clearUploadQueue: function () {
        this.choseFilePath.length = 0;
        this.getIframeContentDocument().forms[0].innerHTML = "";
    },


    //選擇上傳檔案
    chooseFile: function () {
        var uploadfile;
        if (this.choseFilePath.length == this.settings.maximumFilesUpload) {
            if (this.settings.maximumFilesUpload <= 1) {
                this.choseFilePath.length = 0;
                var files = this.getIframeContentDocument().getElementsByTagName("input");
                if (!files.length) {
                    uploadfile = this.getUploadInput();
                    $(uploadfile).click();
                    return;
                } else {
                    uploadfile = files[0];
                    $(uploadfile).click();
                    return;
                }
            } else {
                return;
            }
        }
        uploadfile = this.getUploadInput();
        $(uploadfile).click();
    }
};


//圖片預覽操作
var perviewImage = {
    timers: [],
    closeImg: {
        before: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAOVSURBVHjaYtTUdGdAA4K/fv3U+Pv3rw+QLfT//3+Gf//+vWNiYtjCwsJyAyj2HiT2//8/sGKAAGJB1gkU9Pj581eNnJyctaamMgM/Py8DIyMDw+fPXxlu3rxfdfPmjaPMzIwtTEzMO2B6AAKIBaH5fw4LC1tHeHgQt7u7PYOOjhIDNzcb2IBfv/4x3LjxiGHr1n3WK1duXPPx45sKJiamKSB9AAHECPIC0GZ3ZmbWzQkJkazu7rYMLCyMDD9//gYZCzWcgYGVlRUozsxw9Oh5hv7+Gb8/fXrnC+TvBAggZhERZb7fv3/PdnCwV7C3twT69w+DlpYcw5s3HxkeP34FdP53IPsDg6qqNAMXFxvQIA4GoGXMFy9eVgK6eg1AADH9/ftbW0hIxEpFRQms0MBAlYGDg51BQ0OegZ2dneH58zdAMRUGKSlhBnFxQYY7dx4CvfSHQVBQyAqkFyCAmIWEFDOlpaVtgQHH8O7dB4aXLz8wqKjIMHBysoE1SUqKMCgoSIC90te3lGHNmu0MDx8+Yfjx4xvQmz9eAgQQCzAwhBiBIfX69RugwC+GR4+eAl3yliEx0Y+Bl5eDQU5ODBwG3d0LGdau3QH0AjMwLFiBruQEBjCTEEAAsYBC+du3HwxPnjxnAMY90JCfoLBlePXqLdAAabDNX778AHvl37+/QP9DYubfP0haAAggJlAi+fr1M8Pbt2+Bml4z8PBwMxQURDMoK0uDbf78+QfYJY2N2Qy2thZA//8CGsIMtOg70MI/7wACiAkYkluAfmH48+cPMOHwMbS1FTJoaspB/bwYqHE6w4cP3xn4+DgYWltzgAGqywCMNbABQBdsAQggJmAsX/3+/esxkPNAoX7jxgNQomKYMWMtw65dRxkuXLjGMHHiEobv338x3Lv3DEhDLAO6+hjQq1cBAohRWdkOqOGvOwcHz2Z1dU1WcXEJBgkJYYbbtx+AExIogH/9+s2gra0KDOgPwLTxmOHKlfO/v3z55AtM0jsBAggYjfKg0Lz769eP958/f7FnZ2djAyYUBhERQWBUcgLDhItBWFiY4f37j8AYeshw/frVr1++fCwFal4O8iZAAIENAKdpRoZTwLg99/Llc8VPnz7JffnyFWQwMAa+Mdy/fw+YmW4w3Lp1/eiPH19zgJqXwfIQQACBvQDNiaBsC/K/IDCQNICKfNjYWIVAYQNMH++AIb4FGPrg7IycgwECDADIUZC5UWvTuwAAAABJRU5ErkJggg==",
        after: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA3XAAAN1wFCKJt4AAAAB3RJTUUH1wwbFhkQHxvdFgAAArpJREFUeNplz1to1QUAx/HP/3/O2c7OrudsR8vmamOL2hw5LaQHgxKCLvQSRVgPFhJKo4cyMsmxKNQgfOuhfKxICQTpocvAIFhai/WSTNIcnK3pbu12tnO2cwsfbZ+H3+MXfgGbfURDgn0xHgiIFskUuPgOE/7njsBxahsYqAnDN1p3765N9/QIYzGL4+Myw8PlbC53fp23j5HZFBhgSxPft27f3tfX36+ure2O+sbKiitnzrg2MjK/xjNH+RUCeJbo41xsSyb3PtR/WLQuLhIGVAJKlEsUSyUBrp8966+xsdkl+o7zTwiP8mqSvffu6ZMLs+565YAVWRvL1xSWrpufvmHr/v3y1dVu30pHIuk4pxCEiCQ4nIyEYk15heakmm3bdR06Zrq0LjM3ruPNI+o7O8V7uy1NTkjV10vw4ns0Rw6Q7uCTdLwS1LfMyM+Mytxa0r73aVse2adp52Oau7pd/eGCq4MHNUxPKc4sy1dEylwOt3FPNUH09gTrWhILSr+d9N3pQfGGpHRXjz9/+tHoqRe0t8yqasyK1lKNKlrDdYpVCEqUixRLLBZTep98DkD7zofFO3pVGqlqJlJDDDEK4TkmQlbXc+QWGZ9P2TMwpHXHLpnL541+dVRtMuWp00NmGncpxCkUCLDGWDjJWp6LG0XmJtn6xOu2PrjLzUvn3fr6JdVXP3btmyNqGlN2vHbC/Dxry5SZ+pTfIyh3MN3Jyxt54cKVYYXVKZPn3peIFkTK5G5ckp34W+bLE7IjeWGOOT78gp8DQPwzBtt5dymkkqTmbuIpYnUEAblZsldIrLLB0AGeX2QlAEDD5xy7n7eWia2GlKsREhaIb9CEZS58wKFRplGJAGD9W36JMXwf9cmKdF1RIlGgrmS1zOU/GDjIyZv8iwoENguRQKqblnqiI8yUWUAWJQD4D4Cg/5i7WltRAAAAAElFTkSuQmCC"
    },


    //獲取預覽元素
    getElementObject: function (elem) {
        if (elem.nodeType && elem.nodeType === 1) {
            return elem;
        } else {
            return document.getElementById(elem);
        }
    },
    //開始圖片預覽
    beginPerview: function (/*檔案上傳控制元件例項*/file, /*需要顯示的元素id或元素例項*/perviewElemId,dcmt) {
        for (var t = 0; t < this.timers.length; t++) {
            window.clearInterval(this.timers[t]);
        }
        this.timers.length = 0;


        var preview_div = this.getElementObject(perviewElemId);


        var MAXWIDTH = preview_div.clientWidth;
        var MAXHEIGHT = preview_div.clientHeight;


        if (file.files && file.files[0]) { //此處為Firefox,Chrome以及IE10的操作
            preview_div.innerHTML = "";
            var img = document.createElement("img");
            preview_div.appendChild(img);
            img.style.visibility = "hidden";
            img.onload = function () {
                var rect = perviewImage.clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight);
                img.style.width = rect.width + 'px';
                img.style.height = rect.height + 'px';
                img.style.marginLeft = rect.left + 'px';
                img.style.marginTop = rect.top + 'px';
                img.style.visibility = "visible";
            }


            var reader = new FileReader();
            reader.onload = function (evt) {
                img.src = evt.target.result;
            }
            reader.readAsDataURL(file.files[0]);
        }
        else {//此處為IE6,7,8,9的操作
            file.select();
            var src = dcmt.selection.createRange().text;


            var div_sFilter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',src='" + src + "')";
            var img_sFilter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='image',src='" + src + "')";


            preview_div.innerHTML = "";
            var img = document.createElement("div");
            preview_div.appendChild(img);
            img.style.filter = img_sFilter;
            img.style.visibility = "hidden";
            img.style.width = "100%";
            img.style.height = "100%";


            function setImageDisplay() {
                var rect = perviewImage.clacImgZoomParam(MAXWIDTH, MAXHEIGHT, img.offsetWidth, img.offsetHeight);
                preview_div.innerHTML = "";
                var div = document.createElement("div");
                div.style.width = rect.width + 'px';
                div.style.height = rect.height + 'px';
                div.style.marginLeft = rect.left + 'px';
                div.style.marginTop = rect.top + 'px';
                div.style.filter = div_sFilter;
                preview_div.appendChild(div);
            }


            //圖片載入計數
            var tally = 0;


            var timer = window.setInterval(function () {
                if (img.offsetHeight != MAXHEIGHT) {
                    window.clearInterval(timer);
                    setImageDisplay()
                } else {
                    tally++;
                }
                //如果超過兩秒鐘圖片還不能載入,就停止當前的輪詢
                if (tally > 20) {
                    window.clearInterval(timer);
                    setImageDisplay()
                }
            }, 100);


            this.timers.push(timer);
        }
    },
    //按比例縮放圖片
    clacImgZoomParam: function (maxWidth, maxHeight, width, height) {
        var param = { width: width, height: height };
        if (width > maxWidth || height > maxHeight) {
            var rateWidth = width / maxWidth;
            var rateHeight = height / maxHeight;


            if (rateWidth > rateHeight) {
                param.width = maxWidth;
                param.height = Math.round(height / rateWidth);
            } else {
                param.width = Math.round(width / rateHeight);
                param.height = maxHeight;
            }
        }


        param.left = Math.round((maxWidth - param.width) / 2);
        param.top = Math.round((maxHeight - param.height) / 2);
        return param;
    },
    //建立預覽元素
    createPreviewElement: function (/*上傳時的檔名*/file, /*預覽時的樣式*/style) {
        style = style || { width: '100px', height: '100px', border: '1px solid #ebebeb' };
        var img = document.createElement("div");
        img.title = file;
        img.style.overflow = "hidden";
        for (var s in style) {
            img.style[s] = style[s];
        }
        var text = document.createElement("div");
        text.style.width = style.width;
        text.style.overflow = "hidden";
        text.style.textOverflow = "ellipsis";
        text.style.whiteSpace = "nowrap";
        text.innerHTML = file;




        var top = 0 - window.parseInt(style.width) - 15;
        var right = 0 - window.parseInt(style.width) + 14;
        var close = document.createElement("img");
        close.setAttribute("filepath", file);
        close.src = this.closeImg.before;
        close.style.position = "relative";
        close.style.top = top + "px";
        close.style.right = right + "px";
        close.style.cursor = "pointer";


        var main = document.createElement("div");
        main.appendChild(img);
        main.appendChild(text);
        main.appendChild(close);
        return main;
    },


    //獲取預覽區域
    getPerviewRegion: function (elem) {
        var perview = $(this.getElementObject(elem));
        if (!perview.find("ul").length) {
            var ul = document.createElement("ul");
            ul.style.listStyleType = "none";
            ul.style.margin = "0px";
            ul.style.padding = "0px";


            var div = document.createElement("div");
            div.style.clear = "both";
            perview.append(ul).append(div);
            return ul;
        } else {
            return perview.children("ul").get(0);
        }
    }
}


看看這個外掛中的那個createIframe方法,對它做一點解釋
//建立iframe
    createIframe: function (/*外掛中指定的dom物件*/elem) {

        var html = "<html>"
                + "<head>"
                + "<title>upload</title>"
                + "<script>"
                + "function getDCMT(){return window.frames['dynamic_creation_upload_iframe'].document;}"
                + "</" + "script>"
                + "</head>"
                + "<body>"
                + "<form method='post' target='dynamic_creation_upload_iframe' enctype='multipart/form-data' action='" + this.settings.url + "'>"
                + "</form>"
                + "<iframe name='dynamic_creation_upload_iframe'></iframe>"
                + "</body>"
                + "</html>";

        this.iframe = $("<iframe name='" + this.iframeName + "'></iframe>")[0];
        this.iframe.style.width = "0px";
        this.iframe.style.height = "0px";
        this.iframe.style.display = "none";

        elem.parentNode.insertBefore(this.iframe, elem);
        var iframeDocument = this.getIframeContentDocument();
        iframeDocument.write(html);
    },
大家應該都看到了這個方法中有一個html變數,它儲存的其實就是文章開頭的那段html。在這段html中我添加了一個function名為getDCMT的函式,這是為了獲取名為dynamic_creation_upload_iframe的iframe所在的document物件。在form中我也去掉了檔案上傳的input控制元件,這是因為我將動態建立input控制元件到這個form中,並且我會將這段html使用js的方式把它新增到一個動態建立的iframe中。為什麼要這樣呢?呵呵 我想聰明的你一定會明白的!


好了外掛做好了,我們如何來使用呢?


首先 將那段外掛js程式碼儲存為notRefreshFilesUpload.js的檔案,方便在頁面上的引用,然後構建包含如下結構的page

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>files upload</title>
    <script src="Scripts/jquery-1.7.1.min.js"></script>
    <script src="Scripts/notRefreshFilesUpload.js"></script>
    <script>
        $(function () {

            var btn = $("#Button1");

            btn.uploadFile({
                url: "WebForm1.aspx",
                fileSuffixs: ["jpg", "png", "gif"],
                buttonFeature: true,
                errorText: "{0}",
                maximumFilesUpload: 5,//最大檔案上傳數
                onComplete: function (msg) {
                    $("#testdiv").html(msg);
                },
                perviewImageElementId: "fileList", //設定預覽圖片的元素id
                perviewImgStyle: { width: '100px', height: '100px', border: '1px solid #ebebeb' }//設定預覽圖片的樣式
            });

            var upload = btn.data("uploadFileData");

            $("#files").click(function () {
                upload.submitUpload();
            });
        });
    </script>

</head>
    <body>
        
        
        <div style="width: 400px; height: 300px; float:left">
            <input id="Button1" type="button" value="選擇檔案" />
            <input id="files" type="button" value="上傳" />
            <div id="fileList" style="margin-top: 10px; padding-top:10px; border-top:1px solid #C0C0C0;font-size: 13px; width:400px">
                
            </div>
        </div>
        <div id="testdiv"></div>
    </body>
</html>


上面的程式碼中已經包含了圖片預覽的功能,使用非常簡單我就不多言了,只需要給定用於顯示圖片的元素id即可,一般用div作為圖片預覽的元素。
這是服務端的方法,在這裡我使用了aspx作為服務端的接收方式,當然你可以換成其他任何語言或形式作為服務端的處理方案(可以是php、jsp、mvc等等)
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            List<string> filenames = new List<string>();

            HttpFileCollection files = Request.Files;

            for (int i = 0; i < files.Count; i++)
            {
                filenames.Add(files[i].FileName);
            }

            Response.Write(string.Join("___", filenames));
            Response.Flush();
            Response.End();
        }
    }
服務端程式碼為多檔案上傳處理的方式,呵呵 也就是說這個外掛也是支援多檔案上傳的,在服務端的程式碼中我僅僅返回了上傳檔案的名稱作為對客戶端的響應,當然你可以返回任何你希望的形式,你只需要在客戶端用js做相應處理即可(即在外掛的complete這個回撥中處理響應,它其中的msg回撥引數將把服務端的響應結果回傳給你)。


好了 一個相容各種瀏覽器,並且支援圖片預覽和無重新整理非同步上傳的純js外掛就搞定了。上個圖看看效果