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

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

之前寫的這個上傳外掛,同事們都覺得還不錯,不過都覺得還不夠完美,於是決定使用業餘時間對此外掛持續優化,可能你過段時間會發現,外掛又增加了新功能什麼的,請注意文章後面評論裡的更新說明。

以前在上傳的時候雖然可以多檔案上傳,但其實是將所有檔案都放到一個form裡面同時提交的,這樣就造成一個問題,在服務端無法對檔案做單個的處理,比如告訴客戶端這個檔案太大了或者上傳發生異常的時候客戶端也只有全部終止再重新上傳。

針對以上這些問題,優化為一個檔案對應一個form的方式,這樣帶來的好處是服務端可以對檔案做單個的處理,精確告知客戶端那個檔案上傳錯誤,並不會影響其他還在上傳的檔案,同時帶來另一個好處就是待上傳的檔案還可以取消上傳操作,這樣的好處是不言而喻的,另外增加了上傳時的loading動畫,目前唯一的不足就是無法在客戶端完美的獲取檔案大小(僅針對IE7,8,9),並且上傳失敗的檔案可以重新提交上傳(增加對上傳失敗檔案的顯示樣式)。

好了話不多說還是將優化過的外掛放上來讓大家一睹為快,這次就直接演示如何使用,外掛的具體原始碼貼在文章後面,有需要的可以去copy下來。先來看個效果圖


現在來介紹下如何使用,首先將文章後面的外掛程式碼拷貝下來並儲存為一個叫file_upload_plug-in.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/file_upload_plug-in.js"></script>
    <script>
        $(function () {
            //var btn = $("#Button1");

            var btn = $("#Button1").uploadFile({
                url: "WebForm1.aspx",
                fileSuffixs: ["jpg", "png", "gif", "txt"],
                maximumFilesUpload: 10,//最大檔案上傳數
                onComplete: function (msg) {
                    $("#testdiv").append(msg + "<br/>");
                },
                onAllComplete: function () {
                    alert("全部上傳完成");
                },
                isGetFileSize: true,//是否獲取上傳檔案大小,設定此項為true時,將在onChosen回撥中返回檔案fileSize和獲取大小時的錯誤提示文字errorText
                onChosen: function (file, obj, fileSize, errorText) {
                    if (!errorText) {
                        $("#file_size").text(file + "檔案大小為:" + fileSize + "KB");
                    } else {
                        alert(errorText);
                        return false;
                    }
                    return true;//返回false將取消當前選擇的檔案
                },
                perviewElementId: "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 id="file_size" style="width: 400px; border-bottom: 1px solid #C0C0C0;"></div>
        <div style="width: 400px; height: 300px;">
           <div style="font-size: 13px; font-weight:bold;color: #808080;font-family:'微軟雅黑','黑體','華文細黑';">對於上傳按鈕和選擇檔案按鈕,你可以使用其他任何形式的元素,可以是圖片或一切你能想到的東西,都是可以的</div>
            <input id="Button1" type="button" value="選擇檔案" />
            <input id="files" type="button" value="上傳" />
            <!-- <div style="width: 420px; height: 180px; overflow:auto;border:1px solid #C0C0C0;">-->
            <div id="fileList" style="margin-top: 10px; padding-top:10px; font-size: 13px; width:400px">
                
            </div>
            <!-- </div>-->
        </div>
        <br/>
        <div id="testdiv"></div>
    </body>
</html>
呵呵 可以看到呼叫程式碼更精簡了,使用變得更簡單了,對於新增加的屬性在外掛的註釋中已經描述得很清楚,你只需一試就能明白,如有不明白的敬請留言

服務端程式碼同樣也使用的asp.net的webform如下(當然,你可以使用任意語言的服務端:java,C#,php,mvc,python都沒得問題)

    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);
            }
            var ran = new Random();
            var time = ran.Next(1000, 5000);
            System.Threading.Thread.Sleep(time);
            if (time > 1000 && time < 3000)
            {//上傳成功,這裡只輸出文件名,作為示例就不儲存檔案了
                Response.Write(string.Join(",", filenames));
            }
            else
            {//上傳失敗
                Response.Write("error");//如果發生錯誤,請一定輸出“error”字串,這樣外掛就能自動解析了
            }
            Response.Flush();
            Response.End();
        }
    }
為了使上傳的情況更加真實,加入了執行緒睡眠來模擬多檔案上傳時由於檔案大小不同而響應不一致的情況,還有就是如果發生錯誤記得輸出“error”字串,方便外掛處理,好了就介紹到這兒 歡迎大家拍磚。

以下是外掛原始碼

/*
    無重新整理非同步上傳外掛
    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為服務端的返回字串)
        },
        onAllComplete: function () {
        },//全部檔案上傳完成觸發的事件

        onChosen: function (file, obj, fileSize, errorText) { //選擇檔案後的回撥函式,(file為選中檔案的本地路徑;obj為當前的上傳控制元件例項;fileSize為當前檔案的大小,errorText為獲取檔案大小時的錯誤提示文字)
            //alert(file);
            return true;//在此回撥中返回false將取消當前選擇的檔案
        },
        maximumFilesUpload: 5,//最大檔案選擇數(當此屬性大於1時,buttonFeature屬性只能為true)
        submitFilesNum: 3,//最大提交上傳數(當觸發submitUpload方法時,檔案上傳的個數)
        onSubmitHandle: function (uploadFileNumber) { //提交上傳時的回撥函式,uploadFileNumber為當前上傳的檔案數量
            //在此回撥中返回false上傳提交將被阻止
            return true;
        },
        onSameFilesHandle: function (file) { //當重複選擇相同的檔案時觸發
            //在此回撥中返回false當前選擇的檔案將從上傳佇列中取消
            return true;
        },
        isGetFileSize: false,//是否獲取檔案大小,預設為false

        isSaveErrorFile: true,//是否儲存上傳失敗的檔案,預設true

        perviewElementId: "",//用於預覽的元素id(請傳入一個div元素的id)

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

    $.fn.uploadFile = function (settings) {

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

        if (settings.perviewElementId) {
            //設定圖片預覽元素的必須樣式
            if (!settings.perviewImgStyle) {
                var perviewImg = document.getElementById(settings.perviewElementId);
                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);


        });
    };
})(jQuery);

//上傳輔助類
function UploadAssist(settings) {
    //儲存設定
    this.settings = settings;
    //已選擇檔案的路徑集合
    this.choseFilePath = [];
    //上傳錯誤檔案集合
    this.uploadError = [];
    //建立的iframe唯一名稱
    this.iframeName = "upload" + this.getTimestamp();
    //提交狀態
    this.submitStatus = true;
    //已經上傳的檔案數
    this.uploadFilesNum = 0;
    //上傳完成計數
    this.uploadNum = 0;
    //針對IE上傳獲取檔案大小時的錯誤提示文字
    this.errorText = "請設定瀏覽器一些引數後再上傳檔案,方法如下(設定一次即可):\n請依次點選瀏覽器選單中的\n'工具->Internet選項->安全->可信站點->自定義級別'\n在彈出的自定義級別視窗中找到 'ActiveX控制元件和外掛' 項,將下面的子項全部選為 '啟用' 後,點選確定。\n此時不要關閉當前視窗,再點選 '站點' 按鈕,在彈出的視窗中將下面複選框的 '√' 去掉,然後點選 '新增' 按鈕並關閉當前視窗。\n最後一路 '確定' 完成並重新整理當前頁面。";
    return this;
}

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

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

        var html = "<html>"
                + "<head>"
                + "<title>upload</title>"
                + "<script>"
                + "function getDCMT(iframeName){return window.frames[iframeName].document;}"
                + "</" + "script>"
                + "</head>"
                + "<body>"
                + "</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);
    },

    //獲取時間戳
    getTimestamp: function () {
        return (new Date()).valueOf();
    },

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

        input.onchange = function () {

            //儲存已經選擇的檔案路徑
            that.choseFilePath.push({ "name": this.name, "value": this.value });

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

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

            var fileSize;
            var errorTxt = null;
            //是否獲取上傳檔案大小
            if (that.settings.isGetFileSize) {
                fileSize = perviewImage.getFileSize(this, dcmt);
                if (fileSize == "error") {
                    fileSize = 0;
                    errorTxt = that.errorText;
                }
            }

            //選中後的回撥
            var chosenStatus = that.settings.onChosen(this.value, this, fileSize, errorTxt);
            if (typeof chosenStatus === "boolean" && !chosenStatus) {
                that.removeFile(this.name);
                return;
            }

            if (that.checkFileIsExist(this.value)) {
                var status = that.settings.onSameFilesHandle(this.value);
                if (typeof status === "boolean" && !status) {
                    that.removeFile(this.name);
                    return;
                }
            }

            //是否開啟了圖片預覽
            if (that.settings.perviewElementId) {
                if (!that.settings.perviewImgStyle) {
                    perviewImage.beginPerview(this, that.settings.perviewElementId, dcmt, fileSuf);
                } else {
                    var ul = perviewImage.getPerviewRegion(that.settings.perviewElementId);
                    var main = perviewImage.createPreviewElement(this.name, this.value, that.settings.perviewImgStyle);
                    var li = document.createElement("li");
                    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).find("img[name]").hover(function () {
                        this.src = perviewImage.closeImg.after;
                    }, function () {
                        this.src = perviewImage.closeImg.before;
                    }).click(function () {
                        that.removeFile($(this).attr("name"));
                        $(this).parents("li").fadeOut(200, function () {
                            $(this).remove();
                        });
                    });

                    perviewImage.beginPerview(this, div, dcmt, fileSuf);
                }
            }

            if (!that.settings.buttonFeature) {
                that.submitUpload();
            }
        };

        var formName = "form" + randomNum;
        var form = $('<form method="post" target="iframe' + randomNum + '" enctype="multipart/form-data" action="' + that.settings.url + '" name="' + formName + '"></form>');
        form.append(input);

        $(dcmt.body).append($("<div></div>").append(form)
            .append($("<iframe name='iframe" + randomNum + "'></iframe>").on("load", function () {
                var dcmt1 = that.getInsideIframeContentDocument(this.name);
                if (dcmt1.body.innerHTML) {
                    //開始上傳下一個檔案
                    that.insideOperation();
                    that.uploadNum++;

                    //注意:上傳失敗的響應文字預設為"error"
                    var responseText = $(dcmt1.body).text();

                    if (responseText == "error" && that.settings.isSaveErrorFile) {
                        //儲存上傳失敗的檔案
                        that.uploadError.push(this.name.replace("iframe", "input"));
                    }

                    var obj = that.getObjectByName(this.name.replace("iframe", "input"));
                    if (obj) {
                        //是否開啟了預覽
                        if (that.settings.perviewElementId) {
                            var closeImg = $("#" + that.settings.perviewElementId).find("img[name='" + obj.name + "']");
                            closeImg.next().hide();
                            if (responseText !== "error") {
                                //對於上傳成功的檔案,將它從預覽中刪除
                                closeImg.parents("li").fadeOut("slow", function () {
                                    $(this).remove();
                                });
                            } else {
                                //上傳失敗的檔案,加亮顯示
                                closeImg.css("visibility", "visible").parents("li").css({
                                    "border": "1px solid #ff9999",
                                    "background-color": "#ffdddd"
                                });
                            }
                        }
                    }

                    if (that.settings.onComplete) {
                        that.settings.onComplete(dcmt1.body.innerHTML);
                    }

                    if (that.uploadNum == that.uploadFilesNum) {
                        that.submitStatus = true;
                        that.clearUploadQueue();
                        that.uploadFilesNum = 0;
                        that.uploadNum = 0;
                        that.settings.onAllComplete();
                    }

                    dcmt1.body.innerHTML = "";
                }
            })));
        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 (iframeName) {
        return this.getIframeWindow().getDCMT(iframeName);
    },

    //獲取上傳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 sbmtNum = this.settings.submitFilesNum;
        var len = this.choseFilePath.length;
        var dcmt = this.getIframeContentDocument();
        var that = this;

        if (!len) return;
        if (!this.submitStatus) return;
        this.filesNum = len;

        //設定有效上傳數量,有可能選擇的檔案小於設定的提交數量
        var advisableSubmitNum = sbmtNum < len ? sbmtNum : len;

        this.uploadFilesNum = advisableSubmitNum;

        this.submitStatus = false;
        for (var i = 0; i < advisableSubmitNum; i++) {
            (function (n) {
                var time = (n + 1) * 500;
                window.setTimeout(function () {
                    var obj = that.choseFilePath[n];
                    var formName = obj.name.replace("input", "form");
                    that.forEach(dcmt.forms, function () {
                        if (this.name == formName) {
                            this.submit();
                            return false;
                        }
                    });
                    if (that.settings.perviewElementId) {
                        //用於設定上傳loading圖片顯示 
                        var imgclose = $("#" + that.settings.perviewElementId).find("img[name='" + obj.name + "']");
                        imgclose.next().show();
                        imgclose.css("visibility", "hidden");
                    }
                }, time);
            })(i);
        }
    },
    //內部提交操作,外部不能呼叫
    insideOperation: function () {
        var len = this.choseFilePath.length;
        var dcmt = this.getIframeContentDocument();
        var that = this;

        if (!len) return;
        var obj = this.choseFilePath[this.uploadFilesNum];

        if (obj && obj.name) {
            this.uploadFilesNum++;
            (function (o) {
                window.setTimeout(function () {
                    var formName = o.name.replace("input", "form");

                    that.forEach(dcmt.forms, function (i) {
                        if (this.name == formName) {
                            this.submit();
                            return false;
                        }
                    });

                    if (that.settings.perviewElementId) {
                        //用於設定上傳loading圖片顯示 
                        var imgclose = $("#" + that.settings.perviewElementId).find("img[name='" + o.name + "']");
                        imgclose.next().show();
                        imgclose.css("visibility", "hidden");
                    }
                }, 300);
            })(obj);
        }
    },
    //檢查檔案是否可以上傳
    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) {
                var div = n.parentNode.parentNode;
                div.parentNode.removeChild(div);
                return false;
            }
        });
    },

    //將指定上傳的檔案從上傳佇列中刪除
    removeFile: function (name) {
        var that = this;
        var files = this.getIframeContentDocument().getElementsByTagName("input");
        this.forEach(this.choseFilePath, function (i, n) {
            if (n.name == name) {
                that.forEach(files, function (j, m) {
                    if (m.name == n.name) {
                        var div = m.parentNode.parentNode;
                        div.parentNode.removeChild(div);
                        return false;
                    }
                });
                that.choseFilePath.splice(i, 1);
                return false;
            }
        });
    },
    //獲取選擇的上傳檔案物件
    getObjectByName: function (name) {
        var obj, that = this;
        this.forEach(this.choseFilePath, function (i) {
            if (this.name === name) {
                obj = that.choseFilePath[i];
                return false;
            }
        });
        return obj;
    },
    //清空上傳佇列
    clearUploadQueue: function () {
        var len = this.uploadError.length;
        var that = this;
        if (!len) {
            this.choseFilePath.length = 0;
            this.getIframeContentDocument().body.innerHTML = "";
        } else {
            var errorFiles = this.uploadError.join();
            var newArr = this.choseFilePath.slice(0);
            this.forEach(newArr, function () {
                if (errorFiles.indexOf(this.name) == -1) {
                    that.removeFile(this.name);
                }
            });
        }
        this.uploadError.length = 0;
    },

    //選擇上傳檔案
    chooseFile: function () {
        var uploadfile;
        if (!this.choseFilePath.length && this.settings.perviewElementId) {
            $("#" + this.settings.perviewElementId).find("ul").empty();
        }
        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"
    },
    loading: "data:image/gif;base64,R0lGODlhEAAQAKIGAMLY8YSx5HOm4Mjc88/g9Ofw+v///wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAGACwAAAAAEAAQAAADMGi6RbUwGjKIXCAA016PgRBElAVlG/RdLOO0X9nK61W39qvqiwz5Ls/rRqrggsdkAgAh+QQFCgAGACwCAAAABwAFAAADD2hqELAmiFBIYY4MAutdCQAh+QQFCgAGACwGAAAABwAFAAADD1hU1kaDOKMYCGAGEeYFCQAh+QQFCgAGACwKAAIABQAHAAADEFhUZjSkKdZqBQG0IELDQAIAIfkEBQoABgAsCgAGAAUABwAAAxBoVlRKgyjmlAIBqCDCzUoCACH5BAUKAAYALAYACgAHAAUAAAMPaGpFtYYMAgJgLogA610JACH5BAUKAAYALAIACgAHAAUAAAMPCAHWFiI4o1ghZZJB5i0JACH5BAUKAAYALAAABgAFAAcAAAMQCAFmIaEp1motpDQySMNFAgA7",
    fileImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAEn0lEQVR4nO3aPY4cRQCG4QJt4IjIwV5phYwQlyEi8hEcEiFESgAXQBbHcYiILETASv5h/6Znequ73+dJOpnSfNErlVRfjDl+nPS/bN/vY4zfZo+o+HL2APjMqzHGN7NHVAgAWyQCz0QA2CoReAYCwJaJwMoEgK0TgRUJAHsgAisRAPZCBFYgAOyJCFzY1ewBD3g/xng3ewSruD7j7Kvbr8dCF7DlALwbY/wwewSreDPGeHHGeRG4EFcA9sp14AIEgD0TgTMJAHsnAmcQAI5ABBYSAI5CBBYQALbqnwVnROBEAsBW/TXG+GXBORE4gQCwZX+MMX5ecE4EnkgA2Lq3QwRWIwDsgQisRADYCxFYgQCwJyJwYQLA3pwTgW8vvGX3BIA9WhqBr4cIfEIA2CsRuAABYM9E4EwCwN6JwBkEgCMQgYUEgKMQgQUEgCMRgRMJAEcjAicQAI5IBJ5IADgqEXgCAeDIROARAsDRvR1j/LTgXCICAkDBn0ME7iQAVIjAHQSAEhH4jABQIwIfEQCKROCWAFAlAkMAaMtHQACoS0dAACAcAQGA/yQjIADwQS4CAgCfSkVAAOD/MhEQALhbIgICAPc7fAQEAB526AgIADzusBEQAHiaQ0ZAAODpDhcBAYDTnBOB7y685WwCAKdbGoGbsbEICAAsc4gICAAst/sIXM0eAPf4aozxZvaIFd3cfn+dOUIA2LIXswesbHoEXAFgrqnXAQGA+W4e/8k6BADCBADCBADCBADCBADCvANghr9nD3hGm37LIADM8P3sAc/o9RjjevaI+7gCQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQJgAQNjV7AEPeDnGeD17BJzp5ewBD9lyAK7GGNezR8CRuQJAmABAmABAmABAmABAmABAmABAmABA2L+QtW4QG9di8wAAAABJRU5ErkJggg==",
    //獲取預覽元素
    getElementObject: function (elem) {
        if (elem.nodeType && elem.nodeType === 1) {
            return elem;
        } else {
            return document.getElementById(elem);
        }
    },
    //開始圖片預覽
    beginPerview: function (/*檔案上傳控制元件例項*/file, /*需要顯示的元素id或元素例項*/perviewElemId,/*上傳頁面所在的document物件*/ dcmt,/*檔案字尾名*/ fileSuf) {
        var imgSufs = ",jpg,jpeg,bmp,png,gif,";
        var isImage = imgSufs.indexOf("," + fileSuf.toLowerCase() + ",") > -1;//檢查是否為圖片

        if (isImage) {
            this.imageOperation(file, perviewElemId, dcmt);
        } else {
            this.fileOperation(perviewElemId, fileSuf);
        }
    },
    //一般檔案顯示操作
    fileOperation: function (/*需要顯示的元素id或元素例項*/perviewElemId,/*檔案字尾名*/ fileSuf) {
        var preview_div = this.getElementObject(perviewElemId);

        var MAXWIDTH = preview_div.clientWidth;
        var MAXHEIGHT = preview_div.clientHeight;
        var img = document.createElement("img");
        preview_div.appendChild(img);
        img.style.visibility = "hidden";
        img.src = this.fileImg;
        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 txtTop = 0 - (MAXHEIGHT * 2 / 3);
        $('<div style="text-align:center; position:relative; z-index:100; color:#404040;font: 13px/27px Arial,sans-serif;"></div>')
            .text(fileSuf + "檔案").css("top", txtTop + "px").appendTo(preview_div);

    },
    //圖片預覽操作
    imageOperation: function (/*檔案上傳控制元件例項*/file, /*需要顯示的元素id或元素例項*/perviewElemId,/*上傳頁面所在的document物件*/ 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 (/*關閉圖片名稱*/name,/*上傳時的檔名*/file, /*預覽時的樣式*/style) {
        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("name", name);
        close.src = this.closeImg.before;
        close.style.position = "relative";
        close.style.top = top + "px";
        close.style.right = right + "px";
        close.style.cursor = "pointer";

        var loadtop = (0 - window.parseInt(style.height)) / 2 - 26;
        var loadright = (0 - window.parseInt(style.width)) / 2 + 22;
        var imgloading = document.createElement("img");
        imgloading.src = this.loading;
        imgloading.style.position = "relative";
        imgloading.style.top = loadtop + "px";
        imgloading.style.right = loadright + "px";
        imgloading.style.display = "none";

        var main = document.createElement("div");
        main.appendChild(img);
        main.appendChild(text);
        main.appendChild(close);
        main.appendChild(imgloading);
        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);
        }
    },
    //獲取上傳檔案大小
    getFileSize: function (/*上傳控制元件dom物件*/file, /*上傳控制元件所在的document物件*/dcmt) {
        var fileSize;
        if (file.files && file.files[0]) {
            fileSize = file.files[0].size;
        } else {
            file.select();
            var src = dcmt.selection.createRange().text;
            try {
                var fso = new ActiveXObject("Scripting.FileSystemObject");
                var fileObj = fso.getFile(src);
                fileSize = fileObj.size;
            } catch (e) {
                return "error";
            }
        }
        fileSize = ((fileSize / 1024) + "").split(".")[0];
        return fileSize;
    }
}


</pre><pre>
原理就不多講了,在上一篇文章中其實已經將原理講得比較清楚了,如不清楚可以留言,我會盡力解答。