之前写的这个上传插件,同事们都觉得还不错,不过都觉得还不够完美,于是决定使用业余时间对此插件持续优化,可能你过段时间会发现,插件又增加了新功能什么的,请注意文章后面评论里的更新说明。

以前在上传的时候虽然可以多文件上传,但其实是将所有文件都放到一个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和获取大小时的错误提示文本errorTextonChosen: function (file, obj, fileSize, errorText) {if (!errorText) {$("#file_size").text(file + "文件大小为:" + fileSize + "KB");} else {alert(errorText);return false;}return true;//返回false将取消当前选择的文件},perviewElementId: "fileList", //设置预览图片的元素idperviewImgStyle: { 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,//是否获取文件大小,默认为falseisSaveErrorFile: true,//是否保存上传失败的文件,默认trueperviewElementId: "",//用于预览的元素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,//创建iframecreateIframe: 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>

原理就不多讲了,在上一篇文章中其实已经将原理讲得比较清楚了,如不清楚可以留言,我会尽力解答。

适用于各浏览器支持图片预览,无刷新异步批量上传js插件(2)相关推荐

  1. php上传预览源码,php批量上传五[带预览]-PHP源码

    <script>ec(2);<script> $path=$_SERVER["DOCUMENT_ROOT"];//服务器路径 $i = 0; foreach ...

  2. html5 图片上传,支持图片预览、压缩、及进度显示,兼容IE6+及标准浏览器

    原文:html5 图片上传,支持图片预览.压缩.及进度显示,兼容IE6+及标准浏览器 以前写过上传组件,见 打造 html5 文件上传组件,实现进度显示及拖拽上传,兼容IE6+及其它标准浏览器,对付一 ...

  3. 模仿微信朋友圈 图片浏览 js javascript 支持图片预览,滑动切换,双指缩放,图片缓存

    模仿微信朋友圈 图片浏览 js javascript 支持图片预览,滑动切换,双指缩放,图片缓存 2017年08月10日 12:11:38 阅读数:2311 previewImage-mobile 仿 ...

  4. 仿163网盘无刷新多文件上传系统

    这个仿163网盘无刷新多文件上传系统,并没有用使用.net的控件,完全的手工制作.前台基本上是静态的,跟后台没有关系,所以后台用什么语言做都可以(后面有各个版本的实例下载). 本来觉得这个系统会很复杂 ...

  5. pc 图片预览放大 端vue_移动端Vue.js的图片预览组件,支持放缩、滑动功能!

    功能:图片预览组件,支持双手指放大/缩小,双击放大/缩小,单击消失隐藏. 注:touch事件请手机预览 源码分享 组件参数 data() { return { loading: 2, // 1成功 2 ...

  6. 微信小程序开发聊天室——实时聊天,支持图片预览

    第一次写小程序,老板就让我用websoket写个聊天对话,群聊这种.第一次写聊天功能,第一次用websoket,第一次用小程序,这是在考验我吗?不过我还是研究了一下,终于实现了. 首先看一下界面,界面 ...

  7. java实现文件上传预览_jsp+springmvc实现文件上传、图片上传和及时预览图片

    1.多文件上传:http://blog.csdn.net/a1314517love/article/details/24183273 2.单文件上传的简单示例:http://blog.csdn.net ...

  8. php单图上传并预览,JavaScript实现单图片上传并预览功能

    本文实例为大家分享了JavaScript实现单图片上传并预览功能的具体代码,供大家参考,具体内容如下 单图片上传并实现预览 /*上传图片*/ .addPerson{ line-height: 190p ...

  9. bootstrap上传之后的处理_bootstrap-fileinput 进阶 -- 实现上传失败清除之前的预览图且可以继续上传...

    最终实现的 GIF 效果图 Animation44.gif 资料 正文 需求:在文件上传之后(接口可以正常的访问,只是返回结果是失败的情况下),这个时候需要将原来生成的缩略图清除掉(因为展示的样式会让 ...

最新文章

  1. python 三维画图 坐标值相等_python程序员的表白
  2. 中农王金锋组诚聘微生物组学方向博士后
  3. morphologyEx 形态学
  4. python文件处理系列(一):配置文件处理
  5. OpenGL-坐标系
  6. linux转mysql_[转] linux下安装mysql服务器
  7. 我的小白同事接触白鹭引擎4天,成功做了一款足球小游戏
  8. notepadqq_Notepadqq Linux文本编辑器入门
  9. python能查询MySQL视图_Django框架使用mysql视图操作示例
  10. 清华大学操作系统OS学习(九)——页面置环算法:最优算法、先进先出算法(FIFO)、最近最久未使用算法(LRU)、 CLOCK法、最不常用算法(LFU) 、工作集置换算法、缺页率置环算法
  11. JVM中也有并发GC,CMS机制
  12. 服务端推送技术 Server-sent Events 快速上手
  13. Flurry、友盟、TalkingData移动应用统计分析对比
  14. fluent使用DPM模型计算出的颗粒沉积(trap)数据(.dpm格式)后处理python实现
  15. 质量保证和质量控制的区别
  16. 网页制作用html和sc,实验二:html的基本标签和javasc
  17. 163邮箱的格式怎么写,如何申请电子邮箱?
  18. C语言【程序19】题目:两个乒乓球队进行比赛,各出三人。
  19. Element-ui源码分析之滚动条— el-scrollbar
  20. 索罗斯:国际银行家的金融黑客

热门文章

  1. php redis操作详解
  2. 计算机辅助小学数学教学的研究,计算机辅助小学数学教学研究.doc
  3. vue3中导出excel表格
  4. 超级实用案例,Python 提取 PDF 指定内容生成新PDF
  5. [转]和《红楼梦》咏菊花诗十二首
  6. 【算法】高精度(加减乘除)包含高精度*高精度高精度/高精度
  7. 怎么将excel表格转换成word文档
  8. [leetcode]179 Largest Number
  9. 新手程序员去哪里?避雷小技巧交给你
  10. 人工神经网络的算法原理,深度神经网络工作原理