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. 使用Desktop App Converter打包桌面应用程序

    打包具有安装程序 (.msi) 的应用程序 DesktopAppConverter.exe -Installer C:\Installer\MyAppSetup.msi -Destination C: ...

  2. LeetCode 59. 螺旋矩阵 II(Spiral Matrix II)

    题目描述 给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵. 示例: 输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7 ...

  3. LeetCode 16. 最接近的三数之和(3Sum Closest)

    题目描述 给定一个包括 n 个整数的数组 nums 和 一个目标值 target.找出 nums 中的三个整数,使得它们的和与 target 最接近.返回这三个数的和.假定每组输入只存在唯一答案. 例 ...

  4. html实现高亮检索

    实现效果如下: demo.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  5. koa 基础(二)配置路由

    1.配置路由 app.js // 引入模块 const Koa = require('koa'); const Router = require('koa-router'); // 实例化 let a ...

  6. asp.net 获取服务器及客户端的相关信息

    1. 在ASP.NET中专用属性:获取服务器电脑名:Page.Server.ManchineName获取用户信息:Page.User获取客户端电脑名:Page.Request.UserHostName ...

  7. DP练习题——洛谷P1970花匠

    目录 题目描述: 输入输出格式: 输入格式: 输出格式: 输入输出样例: 输入样例: 输出样例: 题目分析: 解法一: 解法二: 结语: 题目描述: 洛谷\(P1970\) 花匠栋栋种了一排花,每株花 ...

  8. Android Context完全解析与各种获取Context方法

    Context类型 我们知道,Android应用都是使用Java语言来编写的,那么大家可以思考一下,一个Android程序和一个Java程序,他们最大的区别在哪里?划分界限又是什么呢?其实简单点分析, ...

  9. matlab7与win7不兼容

    移动鼠标到其打开图标,右键打开属性,选择兼容性,勾选"以兼容模式运行程序",选择Windows Vista

  10. CSS - 架构

    MaintainableCSS 原子类几乎只有比行内样式少写几个字符这一个优点,缺点倒是一堆,最好别用 一味追求 "永远不要重复同样的事情两次" 会导致过度思考和过度设计,最终出现 ...