冯 海

一个程序新人菜鸟的日记,希望大家多多关照。QQ:32316131

上传文件及验证

1.引言


 这是网上一个 =兄弟写的,我留下来的。

 

 


 

首先跟着小弟先创建一个默认的MVC项目(相信大家都会创建,这里就不演示了)

 

 第一步

 创建一个实体类,这个类是要导入数据库的对象。为了简单起见 小弟创建了个学生对象(记录了他的名字、年龄、各科成绩分数)。

 先声明这只是教学代码,完全是为了演示用的,你真正做产品的代码可没这么简单的定义实体。

复制代码
 1  public class Student
 2     {
 3 
 4        public Student()
 5        {
 6            Id = Guid.NewGuid();
 7        }
 8 
 9         //姓名
10         public string Name { get; set; }
11 
12         //年龄
13         public int Age { get; set; }
14 
15         //语文成绩
16         public int ChineseScore { get; set; }
17 //英文成绩 19 public int EnglishScore { get; set; } 20 21 //数学成绩 22 public int MathScore { get; set; } 23 24 25 }
复制代码

 

第二步

实体创建完了,接下来我们创建一个Empty的控制器(名字取自己喜欢的),(这个也太简单了,我这里就不演示了)直接上结果:

 

小弟在这里创建了个名为UploadExcelController的控制器

复制代码
1  public class UploadExcelController : Controller
2   {
3         // GET: /UploadExcel
4         public ActionResult Index()
5         {
6             return View();
7         }
8   }
复制代码

  第三步

    控制器创建完了接下来做什么呢?估计你也猜到了,所有的不是从界面开始吗!用户访问/UploadExcel/Index 的时候总要出来个交互的东西吧。那就先创建一个交互的视图,光标移到return View();右键创建添加视图

     

 

      

 

      创建视图有很多种方法,我这里只是选择了种简单的具体看个人习惯创建。

      视图创建完毕后,我们先构造一个浏览文件的html标记

      

复制代码
 1 @{
 2     ViewBag.Title = "View";
 3 }
 4 
 5 <h1>Select the Excel file</h1>
 6 
 7 
 8 <div class="input-group ">
 9      @*文件路径的文本框*@
10     <input id="txt_Path" type="text" class="form-control">  
11 
12      @*浏览本地文件按钮*@
13     <span id="btn_Browse" style="cursor:pointer;" onclick="$('input[id=fileUpload]').click();" class="input-group-addon">
14         <i class="glyphicon glyphicon-folder-open"></i>&nbsp;&nbsp;&nbsp;浏览文件
15     </span>
16 </div>
复制代码

 

          小弟这里使用的是MVC自带的bootstrap框架,相信大家也都能看懂,如果看不懂那些标记的话!建议你先花1天时间入门bootstap框架。

    这个时候的效果图应该是这样的

    

       在上传文件到服务器有个常用的html标记是  <input id="fileUpload" type="file" >,没错小弟也用的这个标记,只是它太丑了我把它给隐藏了!用我上面的html标记给替换了。接下来我们开始创建它。

 

 

复制代码
 1 <h1>Select the Excel file</h1>
 2 
 3 
 4 <div class="input-group ">
 5      @*文件路径的文本框*@
 6     <input id="txt_Path" type="text" class="form-control">  
 7 
 8      @*浏览本地文件按钮*@
 9     <span id="btn_Browse" style="cursor:pointer;" onclick="$('input[id=fileUpload]').click();" class="input-group-addon">
10         <i class="glyphicon glyphicon-folder-open"></i>&nbsp;&nbsp;&nbsp;浏览文件
11     </span>
12 </div>
13 
14 <br /><br />
15 
16 
17 @using (Html.BeginForm("Browse", "UploadExcel", FormMethod.Post, new { enctype = "multipart/form-data", id = "form_Upload" }))
18 {
19     @Html.AntiForgeryToken() //防止跨站请求伪造(CSRF:Cross-site request forgery)攻击
20     <input id="fileUpload" type="file" name="file" style="display:none"> //把fileUpload隐藏,原因它太难看了
21 }
复制代码

 

   红色的代码是新增的,Html.BeginForm的扩展方法如果大家不熟悉的话,你就把它看成form表单,因为它最后会生成form表单

 <form  id="form_Upload" action="/UploadExcel/Browse" method="post"  enctype="multipart/form-data">

  .......

 </form>

      哦!这个是基础知识,相信大家也都知道,(题外话:在能使用@HTML扩展方法的时候,我建议大家不要使用原生的HTML标记,为什么呢?因为如果你了解@HTML扩展方法的运行机制的话你就知道我的用意了,   就比如Html.BeginForm它是根据路由去生成的URL,智能的!安全的!如果自己写原生HTML标记的话,难免会产生不安全的URL!)

 

      这个form表单就是我们把Excel文件上传到服务器用的,   

看见form表单的 action="/UploadExcel/Browse",所以我们还要在UploadExcelController控制器里创建第二个名称叫Browse的Action操作

复制代码
 1 public class UploadExcelController : Controller
 2  {
 3         // GET: /UploadExcel
 4         public ActionResult Index()
 5         {
 6             return View();
 7         }
 8 
 9        10 
11         [HttpPost]
12         [ValidateAntiForgeryToken]
13         [HandleError(View = "~/Views/Shared/Error.cshtml")]
14         public ActionResult Browse(HttpPostedFileBase file)
15         {
16 
17         }
18 }
复制代码

     红色部分是我新增加的Action操作,前面说了竟然创建的form表单是上传文件到服务器的,那么这个操作就是处理上传文件用的Action,因为它会改变服务器状态,所以我定义成Post方法。其余2个特性是配合@Html扩展方法用的,一个是防止跨站请求伪造(CSRF:Cross-site request forgery)攻击,一个是统一处理异常页。你也可以不加,跟我们今天的例子没关系。我们先不写这个Action操作的代码,让我们再次回到我们创建的视图页 。

 

 

     竟然我们要使用 <input id="fileUpload" type="file" name="file">的功能,但是又嫌弃它太难看了!怎么办呢? So easy 只需把我们构造的html标记绑定它就行了。在视图页添加如下JS代码

    

复制代码
@section scripts{
<script type="text/javascript"> $('input[id=fileUpload]').change(function () { $('#txt_Path').val($(this).val()); $('#form_Upload').submit(); });
</script>}
复制代码

 

 

     这段JS代码功能就是在<input id="fileUpload" type="file" name="file" style="display:none">选择文件后就把文件路径赋给我们自己构造的文本框里,然后就是提交表单,上传它的选择的文件到我们的服务器。

     请注意灰色那段代码是如何用我们自己构建的按钮绑定到fileUpload的功能上

     

1  @*浏览本地文件按钮*@
2     <span id="btn_Browse" style="cursor:pointer;" onclick="$('input[id=fileUpload]').click();" class="input-group-addon">
3         <i class="glyphicon glyphicon-folder-open"></i>&nbsp;&nbsp;&nbsp;浏览文件
4     </span>

 

现在就来测试下我们写的代码能不能跑!F5运行!如果是以下效果就是正确的

 

 

 

为了浏览文件有响应的效果,我们在视图页加一小段CSS代码

复制代码
 1 @section scripts{
 2 
 3 
 4     <style type="text/css">
 5         #btn_Browse:hover {
 6             color: #3C763D;
 7         }
 8     </style>
 9 
10     <script type="text/javascript">
11         $('input[id=fileUpload]').change(function () {
12             $('#txt_Path').val($(this).val());
13             $('#form_Upload').submit();
14         });
15 
16 
17     
18     </script>}
复制代码

 

 第五步

     到了这里我们的文件已经可以上传到我们服务了,如果不信你在Browse操作打个断点,看看file参数是不是已经接受了文件,如果接受到了说明已经成功一半了!我们还是先不写Browse操作处理Excel文件的代码,焦点还是在视图页上,在本博客第一张效果图里,大家看到浏览文件下面有张table表格吗?小弟创建这个表格只是为了更好的交互效果,让使用的人更直观而已。而且也很简单!

  对了还忘了一个东西,就是上传提交按钮,我们现在来构建它!在视图页form表单下面添加如下代码

      

复制代码
1 @using (Html.BeginForm("Browse", "UploadExcel", FormMethod.Post, new { enctype = "multipart/form-data", id = "form_Upload" }))
2 {
3     @Html.AntiForgeryToken()
4     <input id="fileUpload" type="file" name="file" style="display:none"> 
5 }
6 
//红色部分是我构建的上传提交按钮 7 <div class="input-group pull-right" style="margin:0 0 5px 0"> 8 @Html.RouteLink("开始提交", new { action = "Upload" }, new { id="submit", @class = "btn btn-primary ladda-button ", data_style = "expand-right" }) 9 </div>
复制代码

 

 

 

        @Html.RouteLink扩展方法会根据我定义的路由生成一个<a>锚标签,最后生成如下html标记

      <a id="submit" class="btn  btn-primary ladda-button" data-style="expand-right" href="/UploadExcel/Upload" >开始提交</a>

        

      在这里我把它伪装成了一个button按钮

      

 

  data-style="expand-right"这些属性是我用bootstrap加了个5毛钱的特效,你也可以不用管,也可以使用自己的特效。这个上传提交按钮的功能就是最后一个功能,把经过Browse操作转换成List<T>的数  据导入到我们的数据库。到现在为止我们的导入Excel的页面已经全部完成了,当然我的审美观和前端技术就是渣渣,所以请原谅小弟! href="/UploadExcel/Upload" 这个<a>锚标签会访问UploadExcelController控制器的Upload操作,所以我再添加最后一个操作。在控制器添加如下代码

 

复制代码
 public class UploadExcelController : Controller
    {
        // GET: /UploadExcel
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        [HandleError(View = "~/Views/Shared/Error.cshtml")]
        public ActionResult Browse(HttpPostedFileBase file)
        {

            return null;
        }

        //红色部分是我新增的Action操作,这个操作的作用是把Browse操作转换好的List<T> 通过业务服务层 导入我们数据库
        [HandleError(View = "~/Views/Shared/Error.cshtml")]
        public ActionResult Upload()
        {
            return View("UploadSuccess"); //导入成功的页面 这个页面就留给大家自己设计吧
        }

      }
复制代码

 

 

          现在我们来检查下我们构造好的页面,F5运行。如果是下面的样子我们就全部完成视图页面了

         

 

  

     现在我们把重点放在Excel文件的逻辑处理上了,我们先从Browse操作下手,因为此操作负责把我们上传的Excel文件转换成List Entity对象,只要转换成这个集合对象你后面就可以想怎么插入就怎么插入了 !想插入MSSQL MYSQL 等不同数据都可以呵呵!因为我们用的ORM框架!

      按照我上传的那个思维图,我想我先处理验证!先判断文件的格式是不是Excel的格式。(Excel的格式是根据版本来的 2007-2010 是xlsx,2003是xls)这里我只默认了2007-2010 。

      在Browse操作添加如下代码

      

复制代码
 1         [HttpPost]
 2         [ValidateAntiForgeryToken]
 3         [HandleError(View = "~/Views/Shared/Error.cshtml")]
 4         public ActionResult Browse(HttpPostedFileBase file)
 5         {
 6 
 7             if (string.Empty.Equals(file.FileName) || ".xlsx" != Path.GetExtension(file.FileName))
 8             {
 9                 throw new ArgumentException("当前文件格式不正确,请确保正确的Excel文件格式!");
10             }
11 
12             var severPath = this.Server.MapPath("/files/"); //获取当前虚拟文件路径
13 
14             var savePath = Path.Combine(severPath, file.FileName); //拼接保存文件路径
15 
16             try
17             {
18                 file.SaveAs(savePath);
19                 stus = ExcelHelper.ReadExcelToEntityList<Student>(savePath);
20                 ViewBag.Data = stus;
21                 return View("Index");
22             }
23             finally
24             {
25                 System.IO.File.Delete(savePath);//每次上传完毕删除文件
26             }
27 
28         }
复制代码

 

     

 

 

 

posted @ 2017-06-17 13:51  秋天来了哟  阅读(417)  评论(0编辑  收藏  举报
认识就是缘份,愿天下人都快乐!
QQ: 32316131
Email: 32316131@qq.com