这篇文章主要介绍了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代码如下所示。
<!--导入数据操作层-->
<p id="import" class="modal fade bs-modal-lg" tabindex="-1" role="dialog" aria-labelledby="mymodallabel" aria-hidden="true">
<p class="modal-dialog modal-lg">
<p class="modal-content">
<p class="modal-header bg-primary">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"></button>
<h4 class="modal-title">文件导入</h4>
</p>
<p class="modal-body">
<p style="text-align:right;padding:5px">
<a href="~/content/template/testuser-模板.xls" rel="external nofollow" onclick="javascript:preview();">
<img alt="测试用户信息-模板" src="~/content/images/ico_excel.png" />
<span style="font-size:larger;font-weight:200;color:red">testuser-模板.xls</span>
</a>
</p>
<hr/>
<form id="ffimport" method="post">
<p title="excel导入操作" style="padding: 5px">
<input type="hidden" id="attachguid" name="attachguid" />
<input id="excelfile" type="file">
</p>
</form>
<!--数据显示表格-->
<table id="gridimport" class="table table-striped table-bordered table-hover" cellpadding="0" cellspacing="0" border="0">
</table>
</p>
<p class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" onclick="saveimport()">保存</button>
</p>
</p>
</p>
</p>
对于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<testuserinfo>集合里面,这样我们方便在客户端进行各种属性的操作,它的代码如下所示。
/// <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数据的文件上传、预览、提交的步骤的详细内容。