///作者:柯锦 ///完成时间:2016.08.16 ///多文件异步上传带进度条 (function ($) { function bytesToSize(bytes) { if (bytes === 0) return '0 B'; var k = 1024, // or 1000 sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes) / Math.log(k)); return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i]; } function changeCursor(obj) { obj.style.cursor = 'pointer' } function deleteSelfAndFile(obj) { var that = $(obj); var parentLi = that.parent("li"); that.remove(); parentLi.remove(); } function CreateXMLHttpRequest(target) { var xhr = new XMLHttpRequest(); var ops = $.data(target, "KJajaxUpload").Options; var v, h, evs = { loadstart: 0, loadend: 0, progress: 0, load: 0, error: 0, abort: 0 }; for (v in evs) { if (h = ops['on' + v]) { xhr.upload.addEventListener(v, h, false); } } return xhr; } function InitFileDiv(target, options) { var _that = $(target); _that.empty(); var width = _that.width(); var hasUploadedDiv = $("<div class='KJajaxUpload_HasUploaded' style='width:100%;'/>"); _that.append(hasUploadedDiv);// 上 var divClear = $("<div style='clear:both;'></div>"); var divUploadBody = $("<div class='KJajaxUpload_Body'/>"); var divLeft = $("<div class='KJajaxUpload_Left'/>"); var divRight = $("<div class='KJajaxUpload_Right'/>"); var selectButton = $("<input type='button' class='KJajaxUpload_SelectFile' value='Select File' />"); if (options.Text) { selectButton.val(options.Text); } selectButton.click(function () { SelectFiles(target); }) selectButton.css({ width: options.buttonWidth }) if (options.Available) { selectButton.prop("disabled", false); } else { selectButton.prop("disabled", true); } var uploadButton = $("<input type='button' class='KJajaxUpload_UpButton' value='Upload' style='display:none;'/>"); if (options.uploadText) { uploadButton.val(options.uploadText); } uploadButton.click(function () { UploadFiles(target); }) uploadButton.css({ float: "right", width: options.buttonWidth }) if (options.Available) { uploadButton.prop("disabled", false); } else { uploadButton.prop("disabled", true); } divUploadBody.css({ "overflow": "hidden" }) divLeft.css({ width: "100%", "padding-right": "25%" }) divRight.css({ "margin-left": " -20px" }) _that.append(divClear); divLeft.append(selectButton);// 左 button divLeft.append("<font style='font-size:12px;color:red;margin-left:2px;'>可多选</font>"); divLeft.append(uploadButton); divUploadBody.append(divLeft);// 左 divUploadBody.append(divRight);// 右 文件列表 _that.append(divUploadBody); return _that; } /// 创建蒙版 function CreateMark(target) { var mark = $("<div/>"); mark.css({ width: "100%", height: "100%", position: "fixed", left: 0, top: 0, opacity: 0.5, "z-index": 8, "background-color": "#EFEFF2", "display": "none" }); mark.appendTo($("body")); return mark; } // 创建wrapper function CreateWrapper(target) { var availHeight = screen.availHeight; var width = $(document.body).width() / 2 - 200; var _top = (availHeight - 500) / 2; var contentWrapper = $("<div class='KJajaxUpload_upload_wrapper'>"); var contentState = $("<div class='KJajaxUpload_upload_wrapper_State' style='width:100%;'>"); contentState.html("文件上传中,请稍后..."); var contentBody = $("<div class='KJajaxUpload_upload_wrapper_Body' style='width:100%;'>"); contentWrapper.css({ "text-align": "center", width: "400px", "padding-bottom": "50px", "z-index": 9, position: "fixed", left: width + "px", "top": _top + "px", "background-color": "white", "display": "none" }) contentWrapper.append(contentState); contentWrapper.append(contentBody); contentWrapper.appendTo($("body")); // 内嵌在iframe中 if (top != self) { $(top).scroll(function () { var scrollTop = _top + $(top).scrollTop(); contentWrapper.css({ "top": scrollTop + "px" }); }) } return contentWrapper; } ///创建进度条 function CreateUploadBar(target) { var fileDiv = $(target); var contentText = $.data(target, "KJajaxUpload").KJajaxUpload_upload_wrapper.find(".KJajaxUpload_upload_wrapper_Body"); contentText.empty(); var FileList = fileDiv.find(".fileuploadlist.newfilelist"); $.each(FileList, function (i) { var fileName = $(this).attr("filename"); var divid = $(this).attr("id"); var proressDiv = $("<div id='KJajaxUpload_progress_" + i + "' />"); var fileNameLable = $("<span >" + fileName + "</span>"); var barDiv = $("<div id='KJajaxUpload_bar_" + divid + "' name='KJajaxUpload_bar_" + fileName + "'/>"); barDiv.css({ width: "350px", "margin-left": "20px", height: "22px", border: "1px solid black ", "line-height": "22px" }) var barText1 = $("<div class='KJajaxUpload_progresstext'/>"); barText1.css({ "text-align": "center", "position": "absolute", width: "350px" }); barText1.html("0%"); var barText2 = $("<div class='KJajaxUpload_progresstext'/>"); barText2.css({ "text-align": "center", width: "350px", "background-color": "#ffe48d" }); barText2.html("0%"); var barValue = $("<div class='KJajaxUpload_progressvalue'>"); barValue.css({ position: "relative", overflow: "hidden", width: "0px" }) barValue.append(barText2); barDiv.append(barText1); barDiv.append(barValue); proressDiv.append(fileNameLable); contentText.append(proressDiv); contentText.append(barDiv); }); } // 更新进度 function ChangeProcess(filename, evt) { var loaded = evt.loaded; //已经上传大小情况 var tot = evt.total; //附件总大小 var per = Math.floor(100 * loaded / tot); //已经上传的百分比 var that = $("[name='KJajaxUpload_bar_" + filename + "']"); that.find('div.KJajaxUpload_progressvalue').css("width", per + "%"); that.find('div.KJajaxUpload_progresstext').html(per + "%"); } ///选择文件 function SelectFiles(target) { var options = $.data(target, "KJajaxUpload").Options; var deleteButtonUrl = options.deleteButtonUrl; var uploadButton = $(target).find(".KJajaxUpload_UpButton"); var filters = options.filters; var ele = $("<input type='file'/>"); ele.prop("multiple", options.multiple !== false); ele.hide(); ele.change(function (e) { var exist = false;// 存在相同文件 var files = e.target.files; // 判断扩展名 for (var m = 0; m < files.length; m++) { var item = files[m]; var pos = item.name.lastIndexOf("."); var fileType = item.name.substring(pos + 1).toLowerCase(); if ($.inArray(fileType, filters) == -1) { alert("只能上传" + filters + "类型文件!"); ele.remove(); return } } // 判断是否重名 var filenames = GetalreadyExistFileNames(target); for (var t = 0; t < files.length; t++) { var file = files[t]; if ($.inArray(file.name, filenames) > -1) { exist = true; break; } } if (!exist) { // 显示上传按钮 if (options.clickToUpload) { uploadButton.show(); $.data(target, "KJajaxUpload").HasUploaded = false; uploadButton.prop("disabled", false); } var ul = $("<ul style='margin:0px;'/>"); for (var i = 0, n = files.length; i < n; i++) { var deletebutton = $("<img src='" + deleteButtonUrl + "' onmouseover='changeCursor(this)' class='deleteBtn' />"); deletebutton.click(function () { deleteSelfAndFile(this); checkNewFile(target); }) var guid = new GUID().New(); var li = $('<li class="fileuploadlist newfilelist" id="' + guid + '" filename="' + files[i].name + '" >' + files[i].name + ' (' + bytesToSize(files[i].size) + ' )</li>'); li.append(deletebutton); ul.append(li); } $(target).find(".KJajaxUpload_Right").append(ul); options.onChange.call(this, e); } else { alert("文件名重复"); ele.remove(); return } }); $(target).append(ele); ele.click(); } /// 检查新文件 function checkNewFile(target) { var _target = $(target); if (_target.find(".newfilelist").length == 0) { _target.find(".KJajaxUpload_UpButton").hide(); var fileInputs = _target.find(":file"); fileInputs.remove(); } } /// 获取已经存在的文件名列表 function GetalreadyExistFileNames(target) { var that = $(target); var fileExists = that.find(".fileuploadlist"); var fileNames = []; /// 还存在的文件列表 fileExists.each(function () { var filename = $(this).attr("filename"); if ($.inArray(filename, fileNames) == -1) { fileNames.push(filename); } }) return fileNames; } /// 上传文件 function UploadFiles(target) { var that = $(target); var fileInputs = that.find(":file"); var options = $.data(target, "KJajaxUpload").Options; var deleteButtonUrl = options.deleteButtonUrl; var onUploaded = options.onUploaded; if (fileInputs.length > 0) { var total = 0; var uploaded = 0; var reponses = [];// 服务器端返回的数据 var mark = $.data(target, "KJajaxUpload").Mark; var markcontent = $.data(target, "KJajaxUpload").KJajaxUpload_upload_wrapper; var fileExists = that.find(".newfilelist"); var fileNames = []; /// 还存在的文件列表 fileExists.each(function () { var filename = $(this).attr("filename"); if ($.inArray(filename, fileNames) == -1) { fileNames.push(filename); } }) //如果没有文件 if (fileNames.length == 0) { // 设置已上传完毕 $.data(target, "KJajaxUpload").HasUploaded = true; var data = GetAlreadyUploadedFiles(target); onUploaded.call(null, data); return that; } mark.show(); markcontent.show(); CreateUploadBar(target); for (var i = 0; i < fileInputs.length; i++) { var fileinput = fileInputs[i]; var files = fileinput.files; if (files.length > 0) { for (var j = 0, n = files.length; j < n; j++) { if ($.inArray(files[j].name, fileNames) > -1) { total++; var filename = files[j].name; var paramData = options.formData; var data = new FormData(); data.append("uploadedfile[" + j + "]", files[j]); if (paramData != null) { for (var k in paramData) { data.append(k, paramData[k]); } } var xhr = CreateXMLHttpRequest(target); xhr.upload.addEventListener("progress", function (data) { return function (e) { ChangeProcess(data, e); } }(filename), false); xhr.upload.addEventListener("loadend", function () { }, false); xhr.upload.addEventListener("load", function () { uploaded++; }, false); xhr.onreadystatechange = function () { if (this.readyState == 4) {// 4 = "loaded" if (this.status == 200) {// 200 = OK reponses.push(this.responseText); if (uploaded == $.data(target, "KJajaxUpload").TotalFiles) { var HasUploaded = that.find(".KJajaxUpload_HasUploaded"); var ul = $("<ul style='margin:0px;'/>"); for (var t = 0; t < reponses.length; t++) { var files = JSON.parse(reponses[t]); for (var i = 0, n = files.length; i < n; i++) { var deletebutton = $("<img src='" + deleteButtonUrl + "' onmouseover='changeCursor(this)' class='deleteBtn' />"); deletebutton.click(function () { deleteSelfAndFile(this); checkNewFile(target); }) var guid = new GUID().New(); var li = $('<li class="fileuploadlist" id="' + guid + '" filename="' + files[i].Name + '" filepath="' + files[i].FilePath + '" ><a target="_blank" href="' + files[i].FileUrl + '">' + files[i].Name + '</a> </li>'); li.append(deletebutton); ul.append(li); } } that.find(".KJajaxUpload_Right").empty(); HasUploaded.append(ul); fileInputs.remove(); Uploaded(target); // 设置已上传完毕 $.data(target, "KJajaxUpload").HasUploaded = true; var data = GetAlreadyUploadedFiles(target); /// 调用回调函数 onUploaded.call(null, data); } } else { alert("Problem retrieving XML data"); } } }; xhr.open("POST", options.url, true); xhr.send(data); } } var state = $.data(target, "KJajaxUpload"); state.TotalFiles = total; $.data(this, "KJajaxUpload", state); } } } else { var data = GetAlreadyUploadedFiles(target); onUploaded.call(null, data); } return that; } /// 上传完毕 function Uploaded(target) { alert("文件上传完毕"); var mark = $.data(target, "KJajaxUpload").Mark; var markcontent = $.data(target, "KJajaxUpload").KJajaxUpload_upload_wrapper; mark.hide(); markcontent.find(".KJajaxUpload_upload_wrapper_Body").empty(); markcontent.hide(); var that = $(target); var fileInputs = that.find(":file"); fileInputs.remove(); var uploadButton = that.find(".KJajaxUpload_UpButton"); uploadButton.prop("disabled", true); } ///初始化已有的数据 function AlreadFiles(target, options) { var that = $(target); var deleteButtonUrl = options.deleteButtonUrl; var files = options.AlreadFiles; var HasUploaded = that.find(".KJajaxUpload_HasUploaded"); if (files.length > 0) { var ul = $("<ul style='margin:0px;'/>"); for (var i = 0, n = files.length; i < n; i++) { var deletebutton = $("<img src='" + deleteButtonUrl + "' onmouseover='changeCursor(this)' class='deleteBtn' />"); deletebutton.click(function () { deleteSelfAndFile(this); checkNewFile(target); }) var pos = files[i].lastIndexOf("\\"); var filepos = files[i].lastIndexOf("uploadFile"); var reg = /[\\\/]/g; var filePath = files[i]; var fileUrl = files[i].substr(filepos).replace(reg, '/'); var fileName = files[i].substr(pos + 1); fileName = fileName.substr(fileName.lastIndexOf("_S_") + 3); var guid = new GUID().New(); var li = $('<li class="fileuploadlist" id="' + guid + '" filename="' + fileName + '" filepath="' + filePath + '" ><a target="_blank" href="' + fileUrl + '">' + fileName + '</a> </li>'); li.append(deletebutton); ul.append(li); } HasUploaded.append(ul); } } // 获取已经上传的文件 function GetAlreadyUploadedFiles(target) { var that = $(target); var HasUploaded = that.find(".KJajaxUpload_HasUploaded li"); var datas = []; HasUploaded.each(function () { var data = {}; data.name = $(this).attr("filename"); data.filepath = $(this).attr("filepath"); data.fileurl = $(this).find("a").attr("href"); datas.push(data); }) return datas; } $.fn.KJajaxUpload = function (options, param) { var that = this; if (typeof options == "string") { var method = $.fn.KJajaxUpload.Methods[options]; if (method) { return method(this, param); } } options = options || {}; return this.each(function () { var that = this; var state = $.data(this, "KJajaxUpload"); if (state) { $.extend(state.Options, options); } else { var _options = $.extend({}, $.fn.KJajaxUpload.Default, options); InitFileDiv(this, _options); AlreadFiles(this, _options); var TheMark = CreateMark(this); var TheWrapper = CreateWrapper(this); state = $.data(this, "KJajaxUpload", { Options: _options, Mark: TheMark, KJajaxUpload_upload_wrapper: TheWrapper, TotalFiles: 0, HasUploaded: false }); } }) } $.fn.KJajaxUpload.Default = { url: '/Ashx/UploadFilesHandler.ashx?r=' + Math.random(), formData: {},//要传递的参数 Text: "选择文件", buttonWidth: 80,// 按钮宽度 multiple: true, clickToUpload: false, uploadText: "上传", filters: ["doc", "docx", "xls", "xlsx", "txt", "log", "jpg", "png", "gif", "zip", "rar", "cpp"], AlreadFiles: [],// 初始化已经存在的文件 Available: true,// 是否可用 deleteButtonUrl: '/Style/images/delete.jpg',// 删除按钮图片位置 onInit: function () { }, onChange: function () { }, onUploaded: function () { }// 文件上传完毕后的回调函数 }; $.fn.KJajaxUpload.Methods = { options: function (jq) { return $.data(jq[0], "KJajaxUpload").Options; }, // 上传文件 upload: function (jq) { var options = $.data(jq[0], "KJajaxUpload").Options; if (!options.clickToUpload) { return UploadFiles(jq[0]); } else { alert("请点击上传按钮进行上传"); return; } }, // 是否已上传完毕 返回true or false HasUploaded: function (jq) { var option = $.data(jq[0], "KJajaxUpload").Options; if ((!jq.find(".KJajaxUpload_UpButton").is(":visible")) && option.clickToUpload) {// 点击上传但却没有选择文件 return true; } return $.data(jq[0], "KJajaxUpload").HasUploaded; }, GetAlreadyUploadedFiles: function (jq) {// 获取已经上传的文件 包含初始化时的文件 var data = GetAlreadyUploadedFiles(jq); return data; }, setOptions: function (jq, options) { var state = $.data(jq[0], "KJajaxUpload"); var _options = $.extend({}, state.Options, options); InitFileDiv(jq[0], _options); AlreadFiles(jq[0], _options); state.Options = _options; $.data(jq[0], "KJajaxUpload", state); }, ClearData: function (jq) { var option = {}; option.AlreadFiles = []; $.fn.KJajaxUpload.Methods.setOptions(jq, option); } }; })(jQuery)
function GUID() { this.date = new Date(); /* 判断是否初始化过,如果初始化过以下代码,则以下代码将不再执行,实际中只执行一次 */ if (typeof this.newGUID != 'function') { /* 生成GUID码 */ GUID.prototype.New = function () { this.date = new Date(); var guidStr = ''; sexadecimalDate = this.hexadecimal(this.getGUIDDate(), 16); sexadecimalTime = this.hexadecimal(this.getGUIDTime(), 16); for (var i = 0; i < 9; i++) { guidStr += Math.floor(Math.random() * 16).toString(16); } guidStr += sexadecimalDate; guidStr += sexadecimalTime; while (guidStr.length < 32) { guidStr += Math.floor(Math.random() * 16).toString(16); } return guidStr; //return this.formatGUID(guidStr); } /* * 功能:获取当前日期的GUID格式,即8位数的日期:19700101 * 返回值:返回GUID日期格式的字条串 */ GUID.prototype.getGUIDDate = function () { return this.date.getFullYear() + this.addZero(this.date.getMonth() + 1) + this.addZero(this.date.getDay()); } /* * 功能:获取当前时间的GUID格式,即8位数的时间,包括毫秒,毫秒为2位数:12300933 * 返回值:返回GUID日期格式的字条串 */ GUID.prototype.getGUIDTime = function () { return this.addZero(this.date.getHours()) + this.addZero(this.date.getMinutes()) + this.addZero(this.date.getSeconds()) + this.addZero(parseInt(this.date.getMilliseconds() / 10)); } /* * 功能: 为一位数的正整数前面添加0,如果是可以转成非NaN数字的字符串也可以实现 * 参数: 参数表示准备再前面添加0的数字或可以转换成数字的字符串 * 返回值: 如果符合条件,返回添加0后的字条串类型,否则返回自身的字符串 */ GUID.prototype.addZero = function (num) { if (Number(num).toString() != 'NaN' && num >= 0 && num < 10) { return '0' + Math.floor(num); } else { return num.toString(); } } /* * 功能:将y进制的数值,转换为x进制的数值 * 参数:第1个参数表示欲转换的数值;第2个参数表示欲转换的进制;第3个参数可选,表示当前的进制数,如不写则为10 * 返回值:返回转换后的字符串 */ GUID.prototype.hexadecimal = function (num, x, y) { if (y != undefined) { return parseInt(num.toString(), y).toString(x); } else { return parseInt(num.toString()).toString(x); } } /* * 功能:格式化32位的字符串为GUID模式的字符串 * 参数:第1个参数表示32位的字符串 * 返回值:标准GUID格式的字符串 */ GUID.prototype.formatGUID = function (guidStr) { var str1 = guidStr.slice(0, 8) + '-', str2 = guidStr.slice(8, 12) + '-', str3 = guidStr.slice(12, 16) + '-', str4 = guidStr.slice(16, 20) + '-', str5 = guidStr.slice(20); return str1 + str2 + str3 + str4 + str5; } } }
后端代码
/// <summary> /// UploadFilesHandler 的摘要说明 /// </summary> public class UploadFilesHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { List<FileReponse> list = new List<FileReponse>(); string filePath = System.AppDomain.CurrentDomain.BaseDirectory.ToString() + @"uploadFile\" + DateTime.Now.Year.ToString() + @"\" + DateTime.Now.Month.ToString() + @"\" + DateTime.Now.Day.ToString() + @"\" + System.Web.HttpUtility.UrlDecode(context.Request.Params["userName"].ToString()) + @"\"; if (context.Request.Files.Count > 0) { if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } try { foreach (string files in context.Request.Files) { HttpPostedFile upfile = context.Request.Files[files]; int bufferSize = 1024 * 50;//50K string _guid = Guid.NewGuid().ToString().Replace("-", ""); byte[] buffer = new byte[bufferSize]; int currentCounts = 0;// long totalLength = upfile.ContentLength; string name = upfile.FileName.Substring(upfile.FileName.LastIndexOf("\\") + 1); string fileName = filePath + _guid + "_S_" + name; using (FileStream fs = new FileStream(fileName, FileMode.Create)) { while (currentCounts < totalLength) { int bytes = upfile.InputStream.Read(buffer, 0, bufferSize); fs.Write(buffer, 0, bytes); //Thread.Sleep(1);//0.001s currentCounts += bytes; } } FileReponse item = new FileReponse(); item.Name = name; item.FilePath = fileName; int filepos = item.FilePath.LastIndexOf("uploadFile"); item.FileUrl = item.FilePath.Substring(filepos); list.Add(item); } } catch (Exception ex) { } } string reponse = JsonConvert.SerializeObject(list); context.Response.Write(reponse); //context.Response.ContentType = "text/plain"; //context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } } internal class FileReponse { public string Name { get; set; } public string FilePath { get; set; } public string FileUrl { get; set; } }
使用:
var config = {}; config.formData = formData; if (!HasTheRight("HDComplaintsArea")) { config.Available = false; } if (record.Attachments) { config.AlreadFiles = record.Attachments; } config.onUploaded = function (data) { save(data); } $("#filediv").KJajaxUpload(config); $("#btnSave").click(function () { $("#filediv").KJajaxUpload("upload"); }) function save(data) { fields.Attachments = []; for (var i = 0; i < data.length; i++) { fields.Attachments.push(data[i].filepath); } fields.Attachments = JSON.stringify(fields.Attachments); }
图片:
Demo下载:UploadFilesDemo.zip