jfinal  layui easyexcel  这三样开源技术这里就不多介绍了,自行百度了解吧,他们的组合算是一个很高效又不失美观的操作体验。

操作主要分以下几步:

1、建立jfinal的操作环境,建议使用作者提供的demo , 创建一个 jfinal + undertow 的运行环境。undertow运行起来很快,不仅方便调试,而且运行稳定。https://www.jfinal.com/doc

2、引入easyexcel的相关包,我这里使用的是2.0.5版本,网上有很多1.2的版本教程,这里使用的最新的版本,同老版本还是有些区别的,作者提供了相关的demo,可以自己试一下。

<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>test</scope>
</dependency>

3、建立你要导入的数据库表,我这里用的是mysql5.7,并编写你的导入模板。这里就不贴图了,自己亲手做下就行。

4、分别创建几个类文件 jfinal的controller 、service ,easyexcel使用的 excelData、excelDataListener 文件,当然还有前端访问的excelupload.html页面。

easyexcel 使用 Data文件来约束模板文件的标题(头文件),导入字段的类型和excel中cell的顺序

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data; /**
* 基础数据类.用于基础数据表的导入
* 这里的排序和excel里面的排序一致
*
* @author
**/
@Data //使用注解来格式该文件
@HeadRowHeight(20) // 作为导出data的时候设置头文件行高
@ContentRowHeight(20) //作为导出data的时候设置内容行高
@ColumnWidth(25)//设置行宽
public class ExcelData { @ExcelProperty(value = "工号", index = 0) //这里的工号是和excel的标题一致,index 表示第几列数据
private String agentcode;
@ExcelProperty(value = "姓名", index = 1)
private String name;
@ExcelProperty(value = "手机号", index = 2)
private String mobile;
@ExcelProperty(value = "身份证号", index = 3)
private String idno;
@ExcelProperty(value = "执业证号", index = 4)
private String certifno;
@ExcelProperty(value = "机构代码", index = 5)
private String agentgroupcode;
@ExcelProperty(value = "机构名称", index = 6)
private String agentgroupname; public String getAgentcode() {
return agentcode;
} public void setAgentcode(String agentcode) {
this.agentcode = agentcode;
} public String getMobile() {
return mobile;
} public void setMobile(String mobile) {
this.mobile = mobile;
} public String getIdno() {
return idno;
} public void setIdno(String idno) {
this.idno = idno;
} public String getCertifno() {
return certifno;
} public void setCertifno(String certifno) {
this.certifno = certifno;
} public String getAgentgroupcode() {
return agentgroupcode;
} public void setAgentgroupcode(String agentgroupcode) {
this.agentgroupcode = agentgroupcode;
} public String getAgentgroupname() {
return agentgroupname;
} public void setAgentgroupname(String agentgroupname) {
this.agentgroupname = agentgroupname;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

easyexcel的ExcelDataListener 文件 是解析excel时候使用的监听,在读取一行数据的时候都要调用invoke()方法,在解析完excel之后执行 doAfterAllAnalysed() 方法,demo中提供了分批次处理的方法

public class ImBnExcelDataListener extends AnalysisEventListener<ImpBnExcelData> {

    private static final Log log = Log.getLog(ImBnExcelDataListener.class);
/**
* 每隔5条存储数据库,实际使用中可以500条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 500; List<ImpBnExcelData> list = new ArrayList<ImpBnExcelData>();
StringBuilder stringBuilder = new StringBuilder(); @Override
public void invoke(ImpBnExcelData data, AnalysisContext context) {
System.out.println("解析到一条数据:{}"+JSON.toJSONString(data));
list.add(data);
/* list.add(data);
if (list.size() >= BATCH_COUNT) {
System.out.println("解析到一条数据:{}"+data.getAgentcode());
saveData(list);
list.clear();
}else {
saveLastData(list);
list.clear();
}*/
//saveDataByOne(data);
stringBuilder.append("(");
//BnController BnController =new BnController();
String convertdata =convertToStr(data);
stringBuilder.append(convertdata);
stringBuilder.append("),");
} @Override
public void doAfterAllAnalysed(AnalysisContext context) {
String sqlpro = stringBuilder.toString().substring(0,stringBuilder.toString().lastIndexOf(","));
System.out.println(sqlpro);
batchInsert(sqlpro);
//saveDataObj(convertToObj(list));
System.out.println("所有数据解析完成!");
} public String convertToStr(ImpBnExcelData data){
String convertdata = "'"+data.getAgentcode()+"','"
+data.getName()+"','"
+data.getMobile()+"','"
+data.getIdno()+"','"
+data.getCertifno()+"','"
+data.getAgentgroupcode()+"','"
+data.getAgentgroupname()+"','"
+DateUtil.getTodaySecNum()+"','"
+DateUtil.getTodaySec()+"'";
return convertdata;
}
public static void batchInsert(String sqlpro) {
long start = System.currentTimeMillis();
Config config = DbKit.getConfig("datasource");
Connection conn = null;
try {
conn = config.getConnection();
conn.setAutoCommit(false);
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("insert into table (xx,name,mobile,idno,xx,xx,xx,xx,uptime) values ");
stringBuffer.append(sqlpro);
PreparedStatement pst = conn.prepareStatement(stringBuffer.toString());
pst.addBatch();
pst.executeBatch(); conn.commit(); pst.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} long end = System.currentTimeMillis();
System.out.println("批量插入需要时间:"+(end - start)); //批量插入需要时间:24675
}

这里我使用了合成 insert value 值的方法,将读取的excel拼接成一条 insert into 语句,这样会大大提升批量存储效率,比一条条存要快的多,如果你的mysql接收sql语句的长度够,可以写成一条语句,如果不行就要分批进行存储,或者修改mysql.ini的 参数,将max_allowed_packet的值改大就行,这里我修改到了16M。 jfinal提供了多数据源多配置的方法可以使用 DbKit.getConfig() 或Db.use("")的方法直接使用数据源或直接调用jdbc,方便的不要不要的。

Controller 文件是jfinal用来做控制转发的文件,设置好路由之后,直接可以用Controller调用相关方法,在web环境下运行改方法。

public void upbnexcel() {
AjaxMsg ajaxMsg = new AjaxMsg();
try {
String webrootpath = PathKit.getWebRootPath();
//设置文件上传子目录
//String path = "uploads/excel/";
String path =PropKit.get("excel_upload_path");
UploadFile upload = getFile("file", webrootpath + File.separator + path);
File file = upload.getFile();
//获取文件名
String extName = FileUtils.getFileExt(file.getName());
//获取文件上传的父目录
String filePath = upload.getUploadPath();
//时间命名文件
String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + extName;
//重命名原来的文件
file.renameTo(new File(filePath + fileName));
long start = System.currentTimeMillis();
EasyExcel.read(filePath+fileName, ExcelData.class, new ExcelDataListener()).sheet().doRead();
log.info("导入耗时s:"+String.valueOf((System.currentTimeMillis()-start)/1000));
ajaxMsg.setState("success");
ajaxMsg.setMsg("上传成功,耗时"+String.valueOf((System.currentTimeMillis()-start)/1000)+"秒");
} catch (Exception e) {
e.printStackTrace();
ajaxMsg.setState("fail");
ajaxMsg.setMsg("上传失败:"+e.getMessage());
}
renderJson(ajaxMsg);
}

通过web方法,先将excel上传到服务器的upload/excel文件夹下,并通过时间进行命名,然后直接调用 EasyExcel.read方法解析并写入数据库,然后通过ajaxMsg返回页面状态提示。这里有个注意

UploadFile upload = getFile("file", webrootpath + File.separator + path); 中的 "file" 是cos中的约束,必须要这么写,否则会上传失败
EasyExcel.read 提供了很多读取的方式,可以选取自己需要的方式进行调整。调整后别忘关闭操作流。

uploadexcel.html页面引入了layui相关框架,引入的包就不罗列了,直接写相关内容

<body>
<div id="app" class="layui-form">
<div class="container">
<div class="layui-form-item">
<a class="layui-btn layui-btn-warm" href="模板.xlsx" target="_blank">模板下载</a>
</div>
<blockquote class="layui-elem-quote">
<form class="layui-form" action="">
<div class="layui-form-item">
<div class="layui-inline">
<div class="layui-upload">
<button type="button" class="layui-btn layui-btn-normal" id="file">选择文件</button>
<button type="button" class="layui-btn" id="updo">开始上传</button>
</div>
</div>
</div>
</form>
</blockquote>
</div>
</div>
</body>
<script src="../../../static/plugins/layui/layui.js"></script>
<script>
//一般直接写在一个js文件中
layui.use(['layer', 'form', 'upload'], function () {
var layer = layui.layer
, form = layui.form
, upload = layui.upload; //选完文件后不自动上传
var uploadInst = upload.render({
elem: '#file'
, url: '/upexcel'
, auto: false
, accept: 'file' //普通文件
//,multiple: true
, bindAction: '#updo'
, done: function (res) {
//上传完毕回调
if (res.state == "success") {
parent.layer.alert(res.msg);
}
else {
parent.layer.alert(res.msg);
return false;
}
}
});
})
}

下载操作比较简单,注意一下 ajax不能直接下载文件,需要通过 action 或 href 来下载  ,这里我做了两步请求,先通过选择列表中需要下载的项,然后执行id序列化操作,然后再次执行查询和下载操作,才能保存下载的excel文件。

        $("#expdata").on('click', function () {
var checkStatus = table.checkStatus('tablelist'), data = checkStatus.data;
var ids = [];
for (var i = 0; i < data.length; i++) {
ids.push(data[i].id);
}
console.log(ids);
$.ajax({
//type: 'post',
url: '/downExcel',
data: {ids: ids},
success: function (response) {
console.log(response.idstr);
window.location.href="/expExcel?idstr="+response.idstr;
},
});
});
 /**
* 导出excel
*/
public void expExcel(){
try {
//String[] ids = getParaValues("ids[]");
String idstr = getPara("idstr");
HttpServletResponse response=getResponse();
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename=demo.xlsx");
EasyExcel.write(response.getOutputStream(), ExcelData.class).sheet("模板").doWrite(downExceldata(idstr));
// EasyExcel.write(fileName, ImpBnExcelData.class).sheet("模板").doWrite(data());
}catch (Exception e){
}
renderNull();
//renderFile(file,"demo.xlsx");
}
  //下载时候首先执行该方法,并将选中的id拆分组合为字符串,再将字符串进行回传
public void downExcel(){
String[] ids = getParaValues("ids[]");
String idstr = Arrays.toString(ids);
idstr = idstr.substring(1, idstr.length() - 1);
renderJson("idstr",idstr);
}
public List<ImpBnExcelData> downExceldata(String idstr){ List<Record> lists =BnService.me().findByIdstr(idstr);
List<ImpBnExcelData> bndatalist = new ArrayList<>();
for(Record record : lists) {
ImpBnExcelData bnExcelData = new ImpBnExcelData();
ExcelData.setAgentcode(record.getStr("agentcode"));
ExcelData.setAgentgroupcode(record.getStr("agentgroupcode"));
ExcelData.setAgentgroupname(record.getStr("agentgroupname"));
ExcelData.setCertifno(record.getStr("certifno"));
ExcelData.setIdno(record.getStr("idno"));
ExcelData.setMobile(record.getStr("mobile"));
ExcelData.setName(record.getStr("name"));
datalist.add(bnExcelData);
}
return bndatalist;
}
 

jfinal layui easyexcel 实现文件的上传下载的更多相关文章

  1. 在Window的IIS中创建FTP的Site并用C#进行文件的上传下载

    文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服务器计算机上. 然后,远程计算机可以使用 FTP ...

  2. 创建FTP的Site并用C#进行文件的上传下载

    创建FTP的Site并用C#进行文件的上传下载 文件传输协议 (FTP) 是一个标准协议,可用来通过 Internet 将文件从一台计算机移到另一台计算机. 这些文件存储在运行 FTP 服务器软件的服 ...

  3. linux链接及文件互相上传下载

    若排版紊乱可查看我的个人博客原文地址 基本操作 本篇博客主要介绍如何去链接远程的linux主机及如何实现本地与远程主机之间文件的上传下载操作,下面的linux系统是CentOS6.6 链接远程linu ...

  4. Spring实现文件的上传下载

    背景:之前一直做的是数据库的增删改查工作,对于文件的上传下载比较排斥,今天研究了下具体的实现,发现其实是很简单.此处不仅要实现单文件的上传,还要实现多文件的上传. 单文件的下载知道了,多文件的下载呢? ...

  5. SocketIo+SpringMvc实现文件的上传下载

    SocketIo+SpringMvc实现文件的上传下载 socketIo不仅可以用来做聊天工具,也可以实现局域网(当然你如果有外网也可用外网)内实现文件的上传和下载,下面是代码的效果演示: GIT地址 ...

  6. JAVAWEB之文件的上传下载

    文件上传下载 文件上传: 本篇文章使用的文件上传的例子使用的都是原生技术,servelt+jdbc+fileupload插件,这也是笔者的习惯,当接触到某些从未接触过的东西时,总是喜欢用最原始的东西将 ...

  7. SSM框架之中如何进行文件的上传下载

    SSM框架的整合请看我之前的博客:http://www.cnblogs.com/1314wamm/p/6834266.html 现在我们先看如何编写文件的上传下载:你先看你的pom.xml中是否有文件 ...

  8. python使用ftplib模块实现FTP文件的上传下载

    python已经默认安装了ftplib模块,用其中的FTP类可以实现FTP文件的上传下载 FTP文件上传下载 # coding:utf8 from ftplib import FTP def uplo ...

  9. php文件夹上传下载控件分享

    用过浏览器的开发人员都对大文件上传与下载比较困扰,之前遇到了一个php文件夹上传下载的问题,无奈之下自己开发了一套文件上传控件,在这里分享一下.希望能对你有所帮助. 以下是实例的部分脚本文件 这里我先 ...

随机推荐

  1. Python遍历列表删除多个元素或者重复元素

    在遍历list的时候,删除符合条件的数据,结果不符合预期   num_list = [1, 2, 2, 2, 3] print(num_list) for item in num_list: if i ...

  2. 191016Django基础

    一.简单的webserver框架 from wsgiref.simple_server import make_server def login(req): #view函数 print(req[&qu ...

  3. hdjs---1、hdjs爬坑杂记

    hdjs---1.hdjs爬坑杂记 一.总结 一句话总结: 对hdjs这种文档和完善都不是很好的插件,应该先在项目的空页面试,成功后再用到用了框架的项目中 1.hdjs4.0.18引入select2? ...

  4. 后盾网lavarel视频项目---Laravel 安装代码智能提示扩展「laravel-ide-helper」

    后盾网lavarel视频项目---Laravel 安装代码智能提示扩展「laravel-ide-helper」 一.总结 一句话总结: laravel-ide-helper作用是:代码提示 larav ...

  5. C++模板函数实践1

    实践如下: #include <iostream> #include <typeinfo> using namespace std; class Bean{ private: ...

  6. leetcode 75颜色分类

    两趟扫描,由于排序变量的特殊性,使用计数排序方法可以明显降低至O(n)time O(n) space 关于计数排序:https://mp.weixin.qq.com/s/WGqndkwLlzyVOHO ...

  7. kotlin之布尔类型

    var flag1 :Boolean = true val flag2 :Boolean = false if(flag1&&!flag2){ println("flag1& ...

  8. Android共享元素场景切换动画的实现

    安卓5.0系统引入了共享元素,能做出非常炫酷的场景切换效果,这让人非常兴奋同时非常蛋疼,因为低版本没法使用啊,所以今天就跟大家分享一下自己写的一个库,其实只有2个文件而已就可以兼容安卓5.0以下的版本 ...

  9. TCP/IP,Http,Socket的区别

    大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用 ...

  10. 递归选中easyui树

    $(function(){ // var data1 = [ // { // "id": 3, // "text": "3组织", // & ...