基于ASP.NET MVC 4、WebApi、jQuery和FormData的多文件上传方法
2017-05-01 18:06
866 查看
通过<input type='file' />上传文件是网站应用系统的一个经典应用,可参考的文章较多。因为多种原因,笔者不能远程桌面连接服务器,只有通过网站方式上传更新的应用系统文件。正好五一几天,把原来的有关构思编程实现,即巩固了所学的ASP.NET MVC WebApi知识,也做一个通用的文件上传网站。本文不打算介绍实际的通用网站,而是用一个简单实例主要介绍相关技术。
1、构建和初始化路由
控制器采用默认路由,WebApi采用定制路由,见如下全局文件Global、默认过滤器配置、默认控制器路由配置和定制WebApi路由配置程序的代码:
如下是默认的控制器HomeController代码以及多文件上传处理的WebApi代码
下面是HomeController控制器Index方法对应的视图文件。
@Url.Action用于产生 Url。该辅助方法可以根据路由表产生正确的相对地址,在ajax调用参数中也使用了该辅助方法。注意,上述代码的<script src=''>使用了不存在的动作jquery-1.12.4.min.js和控制器scripts,将产生一个类似MySite/scripts/jquery-1.12.4.min.js的Url。
数据对象FormData是一个名值表,提供了append函数增加名值对。如果是<input type='file' />元素,则自动添加文件内容。该对象是2008年由html5引入,获得目前主流的浏览器的支持。
在WebApi中,var httpRequest = HttpContext.Current.Request对应FormData,可以获得名值对,也可以获取文件名和内容。
上述程序在Windows7+IIS+.NET Framwwork 4.0下基于ASP.NET MVC4框架编程实现,在浏览器Firefox53+、Chrome57+、IE11和Windows Edge等测试通过。如下是实际运行的截图。
后记:本文介绍的方法在开发机器上操作没有任何问题,但发布到客户服务器上就抛出异常 Failed to execute, Failed to load XMLHttpRequest...。相关处理方法见拙文ASP.NET WebApi 上传文件时异常 Failed
to execute send on XMLHttpRequest 的一个处理方法。
1、构建和初始化路由
控制器采用默认路由,WebApi采用定制路由,见如下全局文件Global、默认过滤器配置、默认控制器路由配置和定制WebApi路由配置程序的代码:
using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; namespace CSUST.Files { public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() // 全局文件 Global.asax.cs { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); this.SetJsonFormatter(); } private void SetJsonFormatter() { GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); System.Net.Http.Headers.MediaTypeHeaderValue jsonFormatter = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Add(jsonFormatter); // 必须 } } }
using System.Web; using System.Web.Mvc; namespace CSUST.Files { public class FilterConfig // 过滤器配置 FilterConfig.cs { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); } } }
using System.Web.Mvc; using System.Web.Routing; namespace CSUST.Files { public class RouteConfig // 默认控制器路由配置 RouteConfig.cs { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }
using System.Web.Http; namespace CSUST.Files { public static class WebApiConfig // 定制WebApi路由配置 WebApiConfig.cs { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "DefaultApi2", routeTemplate: "api/{controller}/{action}/{id}", defaults: new { action = RouteParameter.Optional, id = RouteParameter.Optional } ); } } }2、Home控制器代码和WebApi控制器代码
如下是默认的控制器HomeController代码以及多文件上传处理的WebApi代码
using System.Web.Mvc; namespace CSUST.Files { public class HomeController : Controller { public ActionResult Index() { return View(); } } }
using System; using System.Web; using System.Web.Http; namespace CSUST.Files { public class FilesApiController : ApiController // FilesApi控制器 { [HttpPost] public string Upload() { try { var httpRequest = HttpContext.Current.Request; var dirName = httpRequest.Form["DirName"]; // 获取 FormData的键值 System.Text.StringBuilder ss = new System.Text.StringBuilder(); ss.Append("成功上传文件" + Environment.NewLine); foreach (string key in httpRequest.Files) // 文件键 { var postedFile = httpRequest.Files[key]; // 获取文件键对应的文件对象 var file = dirName + postedFile.FileName; postedFile.SaveAs(file); ss.Append(file + Environment.NewLine); } return ss.ToString(); } catch (Exception err) { return err.Message; } } } }3、视图文件Index.cshtml
下面是HomeController控制器Index方法对应的视图文件。
@{ Layout = null; } <!DOCTYPE html> <html> <head> <title>文件上传</title> <script type="text/javascript" src='@Url.Action("jquery-1.12.4.min.js", "scripts")'></script> <script type="text/javascript"> function Upload() { var dir = $("#cbDirNames").val(); var f1 = $("#tbFileName1").val(); var f2 = $("#tbFileName2").val(); if ((f1 == null || f1 == "") && (f2 == null || f2 == "")) { alert("至少要上传一个文件。"); return; } var formData = new FormData(); formData.append("DirName", dir); if (f1 != null && f1 != "") { var files = $("#tbFileName1").get(0).files; if (files.length > 0) { formData.append("File1", files[0]); // Add the uploaded image content to the form data collection } } if (f2 != null && f2 != "") { var files = $("#tbFileName2").get(0).files; if (files.length > 0) { formData.append("File2", files[0]); // Add the uploaded image content to the form data collection } } $.ajax({ type: "post", url: '@Url.Action("Upload", "Api/FilesApi")', async: false, data: formData, contentType: false, processData: false, success: function (data, status) { alert(data); }, error: function (xhr, status, err) { alert("ajax调用异常: " + status + "," + err); } }); } </script> </head> <body> <form id="Form1" enctype="multipart/form-data"> <div align="center"> <h2><label>文件远程上传网站</label></h2> <table style="width: 1050px;" border="1"> <tr style="height: 32px"> <td rowspan="2" style="width: 120px;text-align:center"> 文件名 </td> <td colspan="2" align="left"> <input ID="tbFileName1" name="tbFileName1" type="file" style="width: 96%;" multiple="multiple" /> </td> </tr> <tr style="height: 32px"> <td colspan="2" align="left"> <input ID="tbFileName2" name="tbFileName2" type="file" style="width: 96%;" multiple="multiple" /> </td> </tr> <tr style="height: 42px"> <td style="text-align: center">到文件夹</td> <td style="width: 650px; text-align: left;"> <select ID="cbDirNames" style="width: 650px;"> <option>e:\temp\</option> <option>e:\temp1\</option> </select> </td> <td style="height: 42px; text-align:center;"> <input type="button" ID="bnUpload" value="上传文件" onclick="Upload()" style="width: 232px; height: 32px;" /> </td> </tr> </table> </div> </form> </body> </html>上述视图文件使用了jQuery获取网页三个元素的值,即上传的文件夹名cbDirNames、上传文件tbFileName1和tbFileName2,该视图使用jQuery的ajax同步提交多个文件。需要说明如下几点:
@Url.Action用于产生 Url。该辅助方法可以根据路由表产生正确的相对地址,在ajax调用参数中也使用了该辅助方法。注意,上述代码的<script src=''>使用了不存在的动作jquery-1.12.4.min.js和控制器scripts,将产生一个类似MySite/scripts/jquery-1.12.4.min.js的Url。
数据对象FormData是一个名值表,提供了append函数增加名值对。如果是<input type='file' />元素,则自动添加文件内容。该对象是2008年由html5引入,获得目前主流的浏览器的支持。
在WebApi中,var httpRequest = HttpContext.Current.Request对应FormData,可以获得名值对,也可以获取文件名和内容。
文件上传网页Index.cshtml的Form元素中必须有 enctype="multipart/form-data" 属性。
上述程序在Windows7+IIS+.NET Framwwork 4.0下基于ASP.NET MVC4框架编程实现,在浏览器Firefox53+、Chrome57+、IE11和Windows Edge等测试通过。如下是实际运行的截图。
后记:本文介绍的方法在开发机器上操作没有任何问题,但发布到客户服务器上就抛出异常 Failed to execute, Failed to load XMLHttpRequest...。相关处理方法见拙文ASP.NET WebApi 上传文件时异常 Failed
to execute send on XMLHttpRequest 的一个处理方法。
相关文章推荐
- ASP.NET MVC中,怎么使用jquery/ajaxForm上传文件
- asp.net文件上传用到html的file控件,在使用母版页Master,更改form的Enctype=multipart/form-data的方法
- [Asp.net mvc]jquery.form.js无刷新上传
- asp.net/c# 用<input type="file" />实现文件上传,multipart/form-data
- 谈谈基于iframe、FormData、FileReader三种无刷新上传文件的方法
- asp.net中利用jQuery Form插件上传文件
- Asp.Net Mvc 使用jQuery实现Ajax文件上传
- 基于jQuery和Flash的多文件上传插件uploadify在asp.net下session丢失解决方案
- 详细讲解Asp.net MVC上传文件与下载文件的方法
- JQuery按照form上传文件+asp.net后台处理(一)
- 【VS2010】asp.net MVC 上传文件 的方法
- 基于asp.net MVC的无刷新文件上传
- ASP.NET MVC 上传文件方法
- JQuery按照form上传文件+asp.net后台处理(二)
- 基于jQuery和Flash的多文件上传插件uploadify在asp.net下session丢失解决方案
- JQuery文件上传插件ajaxFileUpload在Asp.net MVC中的使用
- asp.net/c# 用<input type="file" />实现文件上传,multipart/form-data
- ASP.NET MVC 使用jquery.form.js 异步上传 在IE下返回值被变为下载的解决办法
- ASP.NET MVC上传文件的几种方法
- asp.net+jquery.form实现图片异步上传的方法(附jquery.form.js下载)