基于MVC+EasyUI的Web开发框架经验总结(10)--在Web界面上实现数据的导入和导出
数据的导入导出,在很多系统里面都比较常见,这个导入导出的操作,在Winform里面比较容易实现,我曾经在之前的一篇文章《Winform开发框架之通用数据导入导出操作》介绍了在Winform里面的通用导入导出模块的设计和开发过程,但在Web上我们应该如何实现呢?本文主要介绍利用MVC4+EasyUI的特点,并结合文件上传控件Uploadify 的使用,实现文件上传后马上进行处理并显示,然后确认后把数据写入数据库的过程。
我们知道,Web上对Excel的处理和Winform的有所差异,如果是在Web上处理,我们需要把Excel文档上传到服务器上,然后读取文件进行显示,所以第一步是实现文件的上传操作,关于文件上传控件,具体可以参考我的文章《基于MVC4+EasyUI的Web开发框架形成之旅--附件上传组件uploadify的使用》。
1、导入数据的界面效果展示在Winform里面,我们处理Excel数据导入的界面如下所示。
在Web上的主界面如下所示。
导入界面如下所示。
2、Web数据导入的处理逻辑和代码为了实现Web上的数据导入导出操作,我们需要增加两个按钮,一个是导入按钮,一个是导出按钮。
<ahref="javascript:void(0)"class="easyui-linkbutton"id="btnImport"iconcls="icon-excel"onclick="ShowImport()">导入</a><ahref="javascript:void(0)"class="easyui-linkbutton"id="btnExport"iconcls="icon-excel"onclick="ShowExport()">导出</a>
导入的JS处理代码如下所示。
//显示导入界面functionShowImport(){$.showWindow({title:'客户联系人-Excel数据导入',useiframe:true,width:1024,height:700,content:'url:/Contact/Import',buttons:[{text:'取消',iconCls:'icon-cancel',handler:function(win){win.close();}}]});}
上面主要就是弹出一个窗口(上面的导入数据窗口),用来方便客户选择Excel文件并保存数据或者下载导入模板等操作的。
然后在Import.cshtml的视图代码里面,我们需要初始化Datagrid和相关的界面元素,初始化DataGrid的代码如下所示。
//实现对DataGird控件的绑定操作functionInitGrid(){varguid=$("#AttachGUID").val();$('#grid').datagrid({//定位到Table标签,Table标签的ID是gridurl:'/Contact/GetExcelData?guid='+guid,//指向后台的Action来获取当前用户的信息的Json格式的数据title:'客户联系人-Excel数据导入',iconCls:'icon-view',height:400,width:function(){returndocument.body.clientWidth*0.9},//自动宽度..................
上面红色部分的内容,就是我们在文件顺利上传到服务器上的时候,根据一个guid的参数初始化DataGrid的列表数据。
下面是附件上传控件uploadify的初始化脚本代码,其中红色部分注意一下,我们需要上传的是一个文件,并且不允许多选,限定上传文件的类型为xls。
文件上传完成后,首先调用CheckExcelColumns控制器函数来检查是否匹配导入模板的字段,如果匹配通过,加载Excel并展示数据到Datagrid里面,否则提示用户按模板格式录入数据。
$(function(){//添加界面的附件管理$('#file_upload').uploadify({'swf':'/Content/JQueryTools/uploadify/uploadify.swf',//FLash文件路径'buttonText':'浏览',//按钮文本'uploader':'/FileUpload/Upload',//处理ASHX页面'queueID':'fileQueue',//队列的ID'queueSizeLimit':1,//队列最多可上传文件数量,默认为999'auto':false,//选择文件后是否自动上传,默认为true'multi':false,//是否为多选,默认为true'removeCompleted':true,//是否完成后移除序列,默认为true'fileSizeLimit':'10MB',//单个文件大小,0为无限制,可接受KB,MB,GB等单位的字符串值'fileTypeDesc':'ExcelFiles',//文件描述'fileTypeExts':'*.xls',//上传的文件后缀过滤器'onQueueComplete':function(event,data){//所有队列完成后事件varguid=$("#AttachGUID").val();ViewUpFiles(guid,"div_files");//提示用户Excel格式是否正常,如果正常加载数据$.ajax({url:'/Contact/CheckExcelColumns?guid='+guid,type:'get',dataType:'json',success:function(data){if(data.Success){InitGrid();//重新刷新表格数据$.messager.alert("提示","文件已上传,数据加载完毕!");}else{$.messager.alert("提示","上传的Excel文件检查不通过。请根据页面右上角的Excel模板格式进行数据录入。");}}});},'onUploadStart':function(file){InitUpFile();//上传文件前,重置GUID,每次不同$("#file_upload").uploadify("settings",'formData',{'folder':'数据导入文件','guid':$("#AttachGUID").val()});//动态传参数},'onUploadError':function(event,queueId,fileObj,errorObj){//alert(errorObj.type+":"+errorObj.info);}});});
为了有效处理数据的导入,我们需要严格保证导入的数据是和模板的字段是匹配的,否则处理容易出错,也没有任何意义。为了实现这个目的,框架里面提供方法对字段进行检查,主要是确保Excel里面包含了完整的字段即可。
///<summary>///检查Excel文件的字段是否包含了必须的字段///</summary>///<paramname="guid">附件的GUID</param>///<returns></returns>publicActionResultCheckExcelColumns(stringguid){CommonResultresult=newCommonResult();try{DataTabledt=ConvertExcelFileToTable(guid);if(dt!=null){//检查列表是否包含必须的字段result.Success=DataTableHelper.ContainAllColumns(dt,columnString);}}catch(Exceptionex){LogTextHelper.Error(ex);result.ErrorMessage=ex.Message;}returnToJsonContent(result);}
而在InitGrid的初始化中的这个GetExcelData的控制器方法如下所示。主要的逻辑就是获取到Excel,并把Excel里面的数据转换为DataTable,最后初始化为实体类列表,并返回给调用页面就可以了。
///<summary>///获取服务器上的Excel文件,并把它转换为实体列表返回给客户端///</summary>///<paramname="guid">附件的GUID</param>///<returns></returns>publicActionResultGetExcelData(stringguid){if(string.IsNullOrEmpty(guid)){returnnull;}List<ContactInfo>list=newList<ContactInfo>();DataTabletable=ConvertExcelFileToTable(guid);if(table!=null){#region数据转换inti=1;foreach(DataRowdrintable.Rows){stringcustomerName=dr["客户名称"].ToString();if(string.IsNullOrEmpty(customerName)){continue;//客户名称为空,记录跳过}CustomerInfocustomerInfo=BLLFactory<Customer>.Instance.FindByName(customerName);if(customerInfo==null){continue;//客户名称不存在,记录跳过}ContactInfoinfo=newContactInfo();info.Customer_ID=customerInfo.ID;//客户IDinfo.HandNo=dr["编号"].ToString();info.Name=dr["姓名"].ToString();..............................//增加一个特殊字段的转义info.Data1=BLLFactory<Customer>.Instance.GetCustomerName(info.Customer_ID);list.Add(info);}#endregion}varresult=new{total=list.Count,rows=list};returnJsonDate(result);}3、Web上数据的导出操作
刚才介绍了数据的导入操作,数据的导出操作相对简单一些,它的JS函数操作如下所示。
//导出Excel数据varexportCondition;functionShowExport(){varurl="/Contact/Export";$.ajax({type:"POST",url:url,data:exportCondition,success:function(filePath){vardownUrl='/FileUpload/DownloadFile?file='+filePath;window.location=downUrl;}});}
虽然数据的导出比较简单一点,但是由于我们需要使用POST方式对数据条件进行提交,因此不像普通的方式下载文件Window.Open(url)就可以实现文件下载了。如果POST方式提交了参数,那么返回的数据即使是文件流,也无法进行有效的下载。
从上面的脚本我们可以看到,里面的exportCondition就是我们需要提交到服务器的条件,服务器根据这个条件进行检索数据,并返回一个Excel文件就可以了。
由于使用ajax这种POST方式无法直接下载文件流,因此,我们需要先根据条件,在服务器上生成文件,返回一个文件路径,再次通过DownloadFile方法进行文件的下载才可以。
因此这个传递的条件也是很重要的,在查询操作的时候,我们可以把对应的条件传递给它。
//绑定搜索按钮的的点击事件functionBindSearchEvent(){//按条件进行查询数据,首先我们得到数据的值$("#btnSearch").click(function(){//得到用户输入的参数//取值有几种方式:$("#id").combobox('getValue'),$("#id").datebox('getValue'),$("#id").val(),combotree('getValue')//字段增加WHC_前缀字符,避免传递如URL这样的Request关键字冲突varqueryData={WHC_Name:$("#txtName").val(),WHC_OfficePhone:$("#txtOfficePhone").val(),WHC_Mobile:$("#txtMobile").val(),WHC_Address:$("#txtAddress").val(),WHC_Email:$("#txtEmail").val(),WHC_Note:$("#txtNote").val()}//将值传递给DataGridInitGrid(queryData);//传递给导出操作exportCondition=queryData;returnfalse;});}
在我们选定某个树的节点的时候,我们也可以传递自定义的条件给它。
//根据消息分组加载指定列表functionloadByGroupTree(node){//赋值给特殊字段,公司和部门查询的时候选择其中一个varqueryParams=$('#grid').datagrid('options').queryParams;varcondition="{id:\""+node.id+"\",groupname:\""+node.text+"\",userid:\""+@Session["UserId"]+"\"}";queryParams.CustomedCondition=condition;//提供给datagrid的条件exportCondition={CustomedCondition:condition};//提供给导出的条件$("#grid").datagrid("reload");$('#grid').datagrid('uncheckAll');}
后台的Export控制器方法主要的逻辑如下所示。
最终是返回一个生成好的文件地址。
最后给一个方法直接下载文件就可以了。
///<summary>///根据路径下载文件,主要用于生成的文件的下载///</summary>///<paramname="filePath">文件路径</param>///<returns></returns>publicActionResultDownloadFile(stringfile){stringrealPath=Server.MapPath(file);stringsaveFileName=FileUtil.GetFileName(realPath);Response.WriteFile(realPath);Response.Charset="GB2312";Response.ContentEncoding=Encoding.GetEncoding("GB2312");Response.ContentType="application/ms-excel/msword";Response.AppendHeader("Content-Disposition","p_w_upload;filename="+HttpUtility.UrlEncode(saveFileName));Response.Flush();Response.End();returnnewFileStreamResult(Response.OutputStream,"application/ms-excel/msword");}
导出的Excel界面效果如下所示。
由于篇幅的原因,这个导入导出的操作就介绍到这里,希望有问题大家共同探讨。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。