這篇文章主要介紹了BootStrap Fileinput外掛程式和Bootstrap table表格外掛程式結合實作檔案上傳、預覽、提交的導入Excel資料操作步驟,需要的朋友可以參考下
bootstrap-fileinput原始碼: https://github.com/kartik-v/bootstrap-fileinput
bootstrap-fileinput線上API:http://plugins.krajee.com/file-input
#bootstrap-fileinput Demo展示:http://plugins.krajee.com/file-basic-usage-demo
這個插件主要是介紹如何處理圖片上傳的處理操作,原先我的Excel導入操作使用的是Uploadify插件,可以參考我隨筆《附件上傳組件uploadify的使用》,不過這個需要Flash控件支持,在某些瀏覽器(如Chrome)就比較麻煩了,因此決定使用一種較為通用的上傳插件,這次首先對基於Bootstrap前端架構的框架系統升級,取代原來的Uploadify插件,這樣頁面上傳功能,在各個瀏覽器就可以無差異的實現了。
一般情況下,我們需要引入下面兩個文件,插件才能正常使用:
bootstrap-fileinput/css/fileinput.min.css bootstrap-fileinput/js/fileinput.min.js
在File input 插件使用的時候,如果是基於Asp.NET MVC的,那麼我們可以使用BundleConfig.cs進行新增對應的引用,加入Bundles集合引用即可。
//添加对bootstrap-fileinput控件的支持 css_metronic.Include("~/Content/MyPlugins/bootstrap-fileinput/css/fileinput.min.css"); js_metronic.Include("~/Content/MyPlugins/bootstrap-fileinput/js/fileinput.min.js"); js_metronic.Include("~/Content/MyPlugins/bootstrap-fileinput/js/locales/zh.js");
在頁面中,我們使用以下HTML程式碼實作介面展示,主要的bootstrap fileinput外掛程式聲明,主要是基礎的介面程式碼
<input id="excelFile" type="file">
Excel導入的的介面展示如下所示。
選擇指定檔案後,我們可以看到Excel的檔案列表,如下介面所示。
上傳檔案後,資料直接展示在彈出層的清單裡面,這裡直接使用了 Bootstrap-table表格外掛程式來展示。
這樣我們就可以把Excel的記錄展示出來,實現了預覽的功能,勾選必要的記錄,然後保存即可提交到伺服器進行保存,實現了Excel資料的真正導入資料庫處理。
2、Excel匯出操作詳細介紹
我們在實際匯入Excel的介面中,HTML程式碼如下所示。
對於bootstrap fileinput的各種屬性,我們這裡使用JS來初始化,這樣方便統一管理和修改。
//初始化Excel导入的文件 function InitExcelFile() { //记录GUID $("#AttachGUID").val(newGuid()); $("#excelFile").fileinput({ uploadUrl: "/FileUpload/Upload",//上传的地址 uploadAsync: true, //异步上传 language: "zh", //设置语言 showCaption: true, //是否显示标题 showUpload: true, //是否显示上传按钮 showRemove: true, //是否显示移除按钮 showPreview : true, //是否显示预览按钮 browseClass: "btn btn-primary", //按钮样式 dropZoneEnabled: false, //是否显示拖拽区域 allowedFileExtensions: ["xls", "xlsx"], //接收的文件后缀 maxFileCount: 1, //最大上传文件数限制 previewFileIcon: '<i class="glyphicon glyphicon-file"></i>', allowedPreviewTypes: null, previewFileIconSettings: { 'docx': '<i class="glyphicon glyphicon-file"></i>', 'xlsx': '<i class="glyphicon glyphicon-file"></i>', 'pptx': '<i class="glyphicon glyphicon-file"></i>', 'jpg': '<i class="glyphicon glyphicon-picture"></i>', 'pdf': '<i class="glyphicon glyphicon-file"></i>', 'zip': '<i class="glyphicon glyphicon-file"></i>', }, uploadExtraData: { //上传的时候,增加的附加参数 folder: '数据导入文件', guid: $("#AttachGUID").val() } }) //文件上传完成后的事件 .on('fileuploaded', function (event, data, previewId, index) { var form = data.form, files = data.files, extra = data.extra, response = data.response, reader = data.reader; var res = data.response; //返回结果 if (res.Success) { showTips('上传成功'); var guid = $("#AttachGUID").val(); //提示用户Excel格式是否正常,如果正常加载数据 $.ajax({ url: '/TestUser/CheckExcelColumns?guid=' + guid, type: 'get', dataType: 'json', success: function (data) { if (data.Success) { InitImport(guid); //重新刷新表格数据 showToast("文件已上传,数据加载完毕!"); //重新刷新GUID,以及清空文件,方便下一次处理 RefreshExcel(); } else { showToast("上传的Excel文件检查不通过。请根据页面右上角的Excel模板格式进行数据录入。", "error"); } } }); } else { showTips('上传失败'); } }); }
上面的邏輯具體就是,設定上傳檔案的後台頁面為:/FileUpload/Upload,以及各種外掛程式的設定參數,uploadExtraData裡面設定的是提交的附加參數,也就是後台控制器接收的參數,其中
.on('fileuploaded', function (event, data, previewId, index) {
的函數處理檔案上傳後的處理函數,如果上傳檔案回傳的結果是成功的,那麼我們再次呼叫ajax來檢查這個Excel的欄位是否符合要求,如下位址:
url: '/TestUser/CheckExcelColumns?guid=' + guid,
如果這個檢查的後台回傳成功的記錄,那麼再次需要把Excel記錄提取出來預覽,並清空bootstrap fileinput檔案上傳插件,方便下次上傳檔案。如下程式碼所示。
if (data.Success) { InitImport(guid); //重新刷新表格数据 showToast("文件已上传,数据加载完毕!"); //重新刷新GUID,以及清空文件,方便下一次处理 RefreshExcel(); } else { showToast("上传的Excel文件检查不通过。请根据页面右上角的Excel模板格式进行数据录入。", "error"); }
其中RefreshExcel就是重新更新上傳的附加參數值,方便下次上傳,否則附加參數的值一直不變化,就會導致我們設定的GUID沒有變化而出現問題。
//重新更新GUID的值,并清空文件 function RefreshExcel() { $("#AttachGUID").val(newGuid()); $('#excelFile').fileinput('clear');//清空所有文件 //附加参数初始化后一直不会变化,如果需要发生变化,则需要使用refresh进行更新 $('#excelFile').fileinput('refresh', { uploadExtraData: { folder: '数据导入文件', guid: $("#AttachGUID").val() }, }); }
而其中InitImport就是獲取預覽資料並展示在Bootstrap-table表格插件上的,關於這個插件的詳細使用,可以回顧下隨筆《基於Metronic的Bootstrap開發框架經驗總結(16)--使用插件bootstrap-table實現表格記錄的查詢、分頁、排序等處理》進行了解即可。
//根据条件查询并绑定结果 var $import; function InitImport(guid) { var url = "/TestUser/GetExcelData?guid=" + guid; $import = $('#gridImport').bootstrapTable({ url: url, //请求后台的URL(*) method: 'GET', //请求方式(*) striped: true, //是否显示行间隔色 cache: false, //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*) pagination: false, //是否显示分页(*) sidePagination: "server", //分页方式:client客户端分页,server服务端分页(*) pageNumber: 1, //初始化加载第一页,默认第一页,并记录 pageSize: 100, //每页的记录行数(*) pageList: [10, 25, 50, 100], //可供选择的每页的行数(*) search: false, //是否显示表格搜索 strictSearch: true, showColumns: true, //是否显示所有的列(选择显示的列) showRefresh: true, //是否显示刷新按钮 minimumCountColumns: 2, //最少允许的列数 clickToSelect: true, //是否启用点击选中行 uniqueId: "ID", //每一行的唯一标识,一般为主键列 queryParams: function (params) { }, columns: [{ checkbox: true, visible: true //是否显示复选框 }, { field: 'Name', title: '姓名' }, { field: 'Mobile', title: '手机' }, { field: 'Email', title: '邮箱', formatter: emailFormatter }, { field: 'Homepage', title: '主页', formatter: linkFormatter }, { field: 'Hobby', title: '兴趣爱好' }, { field: 'Gender', title: '性别', formatter: sexFormatter }, { field: 'Age', title: '年龄' }, { field: 'BirthDate', title: '出生日期', formatter: dateFormatter }, { field: 'Height', title: '身高' }, { field: 'Note', title: '备注' }], onLoadSuccess: function () { }, onLoadError: function () { showTips("数据加载失败!"); }, }); }
最後就是確認提交後,會透過JS提交資料到背景處理,如下程式碼所示。
//保存导入的数据 function SaveImport() { var list = [];//构造集合对象 var rows = $import.bootstrapTable('getSelections'); for (var i = 0; i < rows.length; i++) { list.push({ 'Name': rows[i].Name, 'Mobile': rows[i].Mobile, 'Email': rows[i].Email, 'Homepage': rows[i].Homepage, 'Hobby': rows[i].Hobby, 'Gender': rows[i].Gender, 'Age': rows[i].Age, 'BirthDate': rows[i].BirthDate, 'Height': rows[i].Height, 'Note': rows[i].Note }); } if (list.length == 0) { showToast("请选择一条记录", "warning"); return; } var postData = { 'list': list };//可以增加其他参数,如{ 'list': list, 'Rucanghao': $("#Rucanghao").val() }; postData = JSON.stringify(postData); $.ajax({ url: '/TestUser/SaveExcelData', type: 'post', dataType: 'json', contentType: 'application/json;charset=utf-8', traditional: true, success: function (data) { if (data.Success) { //保存成功 1.关闭弹出层,2.清空记录显示 3.刷新主列表 showToast("保存成功"); $("#import").modal("hide"); $(bodyTag).html(""); Refresh(); } else { showToast("保存失败:" + data.ErrorMessage, "error"); } }, data: postData }); }
3、後台控制器程式碼分析
這裡我們的JS程式碼裡面,涉及了幾個MVC後台的方法處理:Upload、CheckExcelColumns、GetExcelData、SaveExcelData 。這裡分別進行介紹。
檔案上傳的後台控制器方法如下所示。
/// <summary> /// 上传附件到服务器上 /// </summary> /// <param name="fileData">附件信息</param> /// <param name="guid">附件组GUID</param> /// <param name="folder">指定的上传目录</param> /// <returns></returns> [AcceptVerbs(HttpVerbs.Post)] public ActionResult Upload(string guid, string folder) { CommonResult result = new CommonResult(); HttpFileCollectionBase files = HttpContext.Request.Files; if (files != null) { foreach (string key in files.Keys) { try { #region MyRegion HttpPostedFileBase fileData = files[key]; if (fileData != null) { HttpContext.Request.ContentEncoding = Encoding.GetEncoding("UTF-8"); HttpContext.Response.ContentEncoding = Encoding.GetEncoding("UTF-8"); HttpContext.Response.Charset = "UTF-8"; // 文件上传后的保存路径 string filePath = Server.MapPath("~/UploadFiles/"); DirectoryUtil.AssertDirExist(filePath); string fileName = Path.GetFileName(fileData.FileName); //原始文件名称 string fileExtension = Path.GetExtension(fileName); //文件扩展名 //string saveName = Guid.NewGuid().ToString() + fileExtension; //保存文件名称 FileUploadInfo info = new FileUploadInfo(); info.FileData = ReadFileBytes(fileData); if (info.FileData != null) { info.FileSize = info.FileData.Length; } info.Category = folder; info.FileName = fileName; info.FileExtend = fileExtension; info.AttachmentGUID = guid; info.AddTime = DateTime.Now; info.Editor = CurrentUser.Name;//登录人 result = BLLFactory<FileUpload>.Instance.Upload(info); if (!result.Success) { LogTextHelper.Error("上传文件失败:" + result.ErrorMessage); } } #endregion } catch (Exception ex) { result.ErrorMessage = ex.Message; LogTextHelper.Error(ex); } } } else { result.ErrorMessage = "fileData对象为空"; } return ToJsonContent(result); }
檔案上傳處理後,傳回一個通用的CommonResult 的結果對象,也方便我們在JS客戶端進行判斷處理。
而其中檢查我們匯入Excel的資料是否符合列要求的處理,就是判斷它的資料列和我們預先設定好的列名是否一致即可。
//导入或导出的字段列表 string columnString = "姓名,手机,邮箱,主页,兴趣爱好,性别,年龄,出生日期,身高,备注"; /// <summary> /// 检查Excel文件的字段是否包含了必须的字段 /// </summary> /// <param name="guid">附件的GUID</param> /// <returns></returns> public ActionResult CheckExcelColumns(string guid) { CommonResult result = new CommonResult(); try { DataTable dt = ConvertExcelFileToTable(guid); if (dt != null) { //检查列表是否包含必须的字段 result.Success = DataTableHelper.ContainAllColumns(dt, columnString); } } catch (Exception ex) { LogTextHelper.Error(ex); result.ErrorMessage = ex.Message; } return ToJsonContent(result); }
而GetExcelData則是格式化Excel資料到具體的List
/// <summary> /// 获取服务器上的Excel文件,并把它转换为实体列表返回给客户端 /// </summary> /// <param name="guid">附件的GUID</param> /// <returns></returns> public ActionResult GetExcelData(string guid) { if (string.IsNullOrEmpty(guid)) { return null; } List<TestUserInfo> list = new List<TestUserInfo>(); DataTable table = ConvertExcelFileToTable(guid); if (table != null) { #region 数据转换 int i = 1; foreach (DataRow dr in table.Rows) { bool converted = false; DateTime dtDefault = Convert.ToDateTime("1900-01-01"); DateTime dt; TestUserInfo info = new TestUserInfo(); info.Name = dr["姓名"].ToString(); info.Mobile = dr["手机"].ToString(); info.Email = dr["邮箱"].ToString(); info.Homepage = dr["主页"].ToString(); info.Hobby = dr["兴趣爱好"].ToString(); info.Gender = dr["性别"].ToString(); info.Age = dr["年龄"].ToString().ToInt32(); converted = DateTime.TryParse(dr["出生日期"].ToString(), out dt); if (converted && dt > dtDefault) { info.BirthDate = dt; } info.Height = dr["身高"].ToString().ToDecimal(); info.Note = dr["备注"].ToString(); info.Creator = CurrentUser.ID.ToString(); info.CreateTime = DateTime.Now; info.Editor = CurrentUser.ID.ToString(); info.EditTime = DateTime.Now; list.Add(info); } #endregion } var result = new { total = list.Count, rows = list }; return ToJsonContent(result); }
另一個SaveExcelData的函數是處理資料導入的最終處理函數,主要是將集合寫入到特定的資料庫裡面即可,具體程式碼如下圖所示。
#/// <summary> /// 保存客户端上传的相关数据列表 /// </summary> /// <param name="list">数据列表</param> /// <returns></returns> public ActionResult SaveExcelData(List<TestUserInfo> list) { CommonResult result = new CommonResult(); if (list != null && list.Count > 0) { #region 采用事务进行数据提交 DbTransaction trans = BLLFactory<TestUser>.Instance.CreateTransaction(); if (trans != null) { try { //int seq = 1; foreach (TestUserInfo detail in list) { //detail.Seq = seq++;//增加1 detail.CreateTime = DateTime.Now; detail.Creator = CurrentUser.ID.ToString(); detail.Editor = CurrentUser.ID.ToString(); detail.EditTime = DateTime.Now; BLLFactory<TestUser>.Instance.Insert(detail, trans); } trans.Commit(); result.Success = true; } catch (Exception ex) { LogTextHelper.Error(ex); result.ErrorMessage = ex.Message; trans.Rollback(); } } #endregion } else { result.ErrorMessage = "导入信息不能为空"; } return ToJsonContent(result); }
上面这几个函数的代码一般是比较有规律的,不需要一个个去编写,一般通过代码生成工具Database2Sharp批量生成即可。这样可以有效提高Web的界面代码和后台代码的开发效率,减少出错的机会。
整个导入Excel数据的处理过程,所有代码都贴出来了,基本上整个逻辑了解了就可以很好的了解这个过程的代码了。
以上是BootStrap Fileinput外掛程式和表格外掛程式結合實作導入Excel資料的文件上傳、預覽、提交的步驟的詳細內容。更多資訊請關注PHP中文網其他相關文章!