1、简单原生上传
- 无javascript脚本、无进度条;
- 借助iframe实现post提交后的无刷新效果;
- jquery插件ajaxFileUpload.js的实现原型。
Html代码
???<form enctype="multipart/form-data" action="UploadFile_1" method="post" target="frameResult"> ???????<div class="item"> ???????????<input id="File1" name="UserPhoto" type="file" value="" /> ???????????<input type="submit" value="提交上传" /> ???????????<iframe src="about:blank" id="frameResult" name="frameResult"></iframe> ???????</div> ???</form>
后台代码(ASP.NET MVC)
???????[HttpPost] ???????public ActionResult UploadFile_1() ???????{ ???????????string result = "上传成功"; ???????????HttpPostedFileBase file= Request.Files["UserPhoto"]; ???????????file.SaveAs(Server.MapPath("~/Upload/")+ file.FileName); ???????????return Content(result); ???????}
要点说明
- 为<form>标签的action、method设值,以POST方式请求UploadFile_1方法;
- 为<form>标签的enctype属性设值multipart/form-data,让POST请求带上<input type="file">的文件内容;
- 为<form>标签的target属性设值frameResult,让表单的请求响应结果放到名为frameResult的iframe中显示。
2、纯JavaScript异步上传
- 借助HTML5特性实现进度条、上传速度计算;
- 无需<form>标签;
- 不支持IE8、IE9等低版本浏览器。
JavaScript代码,因为不需要<form>标签,html也没什么内容可贴的了。
???var btnUpload = document.getElementById(‘btnUpload‘); ???btnUpload.onclick = function () { ???????var fileInput = document.getElementById(‘File2‘); ???????if (!fileInput.value) { return; } ???????var feature = {}; ???????feature.fileapi = fileInput.files !== undefined; ???????feature.formdata = (typeof window.FormData !== ‘undefined‘); ???????if (!feature.fileapi || !feature.formdata) { ???????????showMessage(‘当前浏览器不支持Html5,请更换高级浏览器‘); ???????????return; ???????} ???????var xhr = new XMLHttpRequest(); ???????var formData = new FormData(); ???????formData.append("UserPhoto", fileInput.files[0]); ???????xhr.open("post", ‘./UploadFile_2‘); ???????//超时时间,单位是毫秒 ???????xhr.timeout = 60 * 1000; ???????//请求结束 ???????xhr.onload = function (event) { ???????????if (xhr.status == 200) { ???????????????showMessage("上传成功"); ???????????????return; ???????????} ???????????if (xhr.status == 404) { ???????????????showMessage("请求路径错误"); ???????????????setProgressBar(0, ‘kb/s‘, ‘hide‘, ‘0%‘); ???????????????return; ???????????} ???????????if (xhr.status == 500) { ???????????????console.error(‘xhr.status == 500‘); ???????????????showMessage("服务器异常"); ???????????} ???????}; ???????//请求异常(不包括404) ???????xhr.onerror = function () { ???????????console.error(‘xhr.onerror‘); ???????????showMessage("请求发生异常"); ???????}; ???????//上传开始事件 ???????xhr.upload.onloadstart = function () { ???????????setProgressBar(0, ‘kb/s‘, ‘hide‘, ‘0%‘); ???????????lastTime = new Date().getTime(); ???????????loadSize = 0; ???????} ???????//上传过程事件,间歇调用该方法用来获取上传过程中的信息 ???????xhr.upload.onprogress = function (event) { ???????????//ProgressEvent.lengthComputable:boolean类型,表示能否计算出文件长度;如果为false,那么ProgressEvent.total则为0. ???????????//简而言之,lengthComputabl等于true就可以做进度计算 ???????????if (!event.lengthComputable) { ???????????????return; ???????????} ???????????//计算上传速度,event.loaded是已发送的大小 ???????????var now = new Date().getTime(); ???????????var timeInterval = (now - lastTime) / 1000; ???????????lastTime = now; ???????????var sizeInterval = event.loaded - loadSize; ???????????loadSize = event.loaded; ???????????var speed = sizeInterval / timeInterval; // 单位b/s ???????????var bspeed = speed; ???????????var units = "b/s"; ???????????if (speed / 1024 > 1) { ???????????????speed = speed / 1024; ???????????????units = ‘kb/s‘; ???????????} ???????????if (speed / 1024 > 1) { ???????????????speed = speed / 1024; ???????????????units = ‘mb/s‘; ???????????} ???????????speed = speed.toFixed(1); ???????????//计算剩余时间 ???????????var resttime = ((event.total - event.loaded) / bspeed).toFixed(1); //单位 秒 ???????????//计算进度百分比 ???????????var precent = (100 * event.loaded / event.total); ???????????pre = Math.floor(precent); ???????????if (bspeed == 0) { ???????????????//setProgressBar方法是控制进度条的, ???????????????//这里代码没贴,在最后源码下载里有 ???????????????//四个参数:上传速度、单位、剩余时间、进度百分比 ???????????????setProgressBar(0, "b/s", ‘infinity‘, ‘noChange‘); ???????????} else { ???????????????setProgressBar(speed, units, resttime, precent + ‘%‘); ???????????} ???????}; ???????//上传终止 ???????xhr.upload.onabort = function () { ???????????console.info(‘xhr.upload.onabort‘); ???????} ???????//上传异常事件 ???????//当网络环境正常时,XMLHttpRequest.status等于404、500并不能触发upload.onerror事件 ???????//当网络环境异常时(offline),会触发upload.onerror事件 ???????xhr.upload.onerror = function () { ???????????console.error(‘xhr.upload.onerror‘); ???????} ???????//文件发送完毕事件 ???????//当网络环境正常时,即使XMLHttpRequest.status等于404、500,仍会被触发upload.onload事件 ???????//当网络环境异常时(offline),不会触发upload.onload事件 ???????xhr.upload.onload = function () { ???????????console.info(‘xhr.upload.onload‘); ???????} ???????//上传超时 ???????xhr.upload.ontimeout = function () { ???????????console.error(‘xhr.upload.ontimeout‘); ???????} ???????//发送请求 ???????xhr.send(formData); ???}
后台接收代码
???????[HttpPost] ???????public ActionResult UploadFile_2() ???????{ ???????????HttpPostedFileBase file = Request.Files["UserPhoto"]; ???????????file.SaveAs(Server.MapPath("~/Upload/") + file.FileName); ???????????return Json("success"); ???????}
要点说明
- 无需 <form> 标签
- 通过判断document.getElementById(‘File2‘).files 及 window.FormData 对象是否为 undefined ,得出当前浏览器是否具备我们所需的HTML5特性;
- FormData对象如同其名称一样以键值对形式存储表单数据;
- 主要借助 xhr.upload 对象的两个事件 onloadstart、onprogress 实现进度条。
3、JQuery异步上传
- 上个例子的Jquery版;
- 同样需要HTML5特性支持,无法在低版本浏览器使用。
???$(‘#btnUpload3‘).click(function () { ???????var $fileInput = $(‘#File3‘); ???????if (!$fileInput.val()) { return; } ???????var feature = {}; ???????//检查是否支持html5 api ???????feature.fileapi = $fileInput.get(0).files !== undefined; ???????feature.formdata = (typeof window.FormData !== ‘undefined‘); ???????if (!feature.fileapi || !feature.formdata) { ???????????showMessage(‘当前浏览器不支持Html5,请更换高级浏览器‘); ???????????return; ???????} ???????var formData = new FormData(); ???????formData.append("UserPhoto", $fileInput[0].files[0]); ???????$.ajax({ ???????????type: ‘post‘, ???????????url: ‘./UploadFile_2‘, ???????????data: formData, ???????????processData: false,//设置为false。因为data值是FormData对象,不需要对数据做处理。 ???????????contentType: false, //设置为false。告诉jQuery不要去设置Content-Type请求头 ???????????xhr: function () { ???????????????var xhr = $.ajaxSettings.xhr(); ???????????????if (xhr.upload) { ???????????????????xhr.upload.onloadstart = uploadStart; ???????????????????xhr.upload.onprogress = uploadProgress; ???????????????????return xhr; ???????????????} ???????????}, ???????????success: function (data, textStatus, jqXHR) { ???????????????showMessage("上传成功"); ???????????}, ???????????error: function (jqXHR, textStatus, errorThrown) { ???????????????showMessage("上传失败"); ???????????} ???????}); ???});
要点说明
- processData、contentType 设置为 false;
- $.ajax()方法中需要为请求设置xhr赋值一个function,用于加工$.ajax()的XmlHttpRequest对象,为xhr.upload 对象的两个事件 onloadstart、onprogress 绑定处理方法,处理方法同例子2一样。最后的源码下载中会有。
4、异步表单插件jquery.form.js
- 前三个例子的集成版,需要 <form> 标签做兼容;
- 当浏览器不支持H5,使用例子1的方式;
- 当浏览器支持H5,使用例子2、3的方式。
html代码
???<form id="form4" enctype="multipart/form-data" action="UploadFile_2" method="post"> ???????<div class="item"> ???????????<h3> ???????????????4、异步表单插件jquery.form.js ???????????</h3> ???????????<input id="File4" name="UserPhoto" type="file" value="" /> ???????????<input id="btnUpload4" type="button" value="提交上传" /> ???????</div> ???</form>
js代码
???$(‘#btnUpload4‘).click(function () { ???????var $fileInput = $(‘#File4‘); ???????if (!$fileInput.val()) { return; } ???????var options = { ???????????type: ‘post‘, ???????????url: ‘./UploadFile_2‘, ???????????success: function (data, textStatus, jqXHR) { ???????????????showMessage("上传成功"); ???????????}, ???????????error: function (jqXHR, textStatus, errorThrown) { ???????????????showMessage("上传失败"); ???????????} ???????} ???????var feature = {}; ???????//检查是否支持html5 api ???????feature.fileapi = $fileInput.get(0).files !== undefined; ???????feature.formdata = (typeof window.FormData !== ‘undefined‘); ???????//如果支持html5,那么就使用进度条 ???????if (feature.fileapi && feature.formdata) { ???????????options = $.extend(options, { ???????????????xhr: function () { ???????????????????var xhr = $.ajaxSettings.xhr(); ???????????????????if (xhr.upload) { ???????????????????????xhr.upload.onloadstart = uploadStart; ???????????????????????xhr.upload.onprogress = uploadProgress; ???????????????????????return xhr; ???????????????????} ???????????????} ???????????}); ???????} ???????$("#form4").ajaxSubmit(options); ???});
要点说明
- jquery.form.js 仍然需要<form>标签作为兼容基础;
- ajaxSubmit(options)方法中的options参数与$.ajax(options)的参数其实是同一个对象,本质就是 ajaxSubmit为 $.ajax 批了一件外套;
- 根据上一点,我们可以使用例子3中同样的手段实现进度条。
源码下载:https://pan.baidu.com/s/1eWiOzvio9EVW2WlYeaKUGA
代码是用VS2015 ASP.NET MVC5写的,我把bin目录内的dll都删了,通过还原 nuget 程序包应该就能运行了。
记录小文件上传的几个例子(含进度条效果,附源码下载)
原文地址:https://www.cnblogs.com/xurongjian/p/9853230.html