java对excle操作:下载、上传以及上传中错误数据动态生成excle给用户下载
工作中经常遇到excle文件的上传下载,这里就总结一下相关的操作,尤其是最后一个方法“上传excle文件校验数据格式,挑出格式错误的数据”网上没有找到相关的例子,自己组合改写了一下,有更好的改进欢迎大家评论交流
其中包括
1、静态excle文件下载
2、excle文件上传
3、动态生成的excle文件下载
4、上传excle文件校验数据格式,挑出格式错误的数据,并动态生成excle文件让用户下载(业务场景:用户下载错误数据按照提示修改后,再次上传文件)
下面直接上代码
一、依赖
pom.xml

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.6.RELEASE</version>
</dependency> <!-- excle操作-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.8</version>
</dependency> <dependency>
<groupId>net.sourceforge.jexcelapi</groupId>
<artifactId>jxl</artifactId>
<version>2.6.10</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.1</version>
</dependency> <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency> </dependencies>
二、相关bean

package com.example.demo.excle.controller;
import java.util.Date;
public class User {
String name;
int age;
Date birthday;
public User(String name, int age, Date birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}

package com.example.demo.excle.controller;
public class Temp {
String username;
String realName;
String deptCode;
String deptName;
String text;
public Temp(String username, String realName, String deptCode, String deptName, String text) {
this.username = username;
this.realName = realName;
this.deptCode = deptCode;
this.deptName = deptName;
this.text = text;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public String getDeptCode() {
return deptCode;
}
public void setDeptCode(String deptCode) {
this.deptCode = deptCode;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
三、Controller(实现)

package com.example.demo.excle.controller; import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder; @RestController
@RequestMapping("/excle")
public class ExcelController { //下载excle静态模板
@GetMapping("/template")
@ResponseBody
public void downloadExcel(HttpServletResponse response, HttpServletRequest request) {
try {
//获取文件的路径
File file = ResourceUtils.getFile("classpath:excle/用户信息表.xlsx");
String fileName = "用户信息表.xlsx" ; // 文件的默认保存名
// 读到流中
InputStream inStream = new FileInputStream(file);//文件的存放路径
// 设置输出的格式
response.reset();
response.setContentType("bin");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("用户信息表.xlsx", "UTF-8"));
// 循环取出流中的数据
byte[] b = new byte[200];
int len; while ((len = inStream.read(b)) > 0){
response.getOutputStream().write(b, 0, len);
}
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
} //下载动态数据
@GetMapping("/download")
@ResponseBody
public void download(HttpServletResponse response) { //模拟数据
List<User> list= new ArrayList<User>();
list.add(new User("zhangsan",12,new Date()));
list.add(new User("zhangsan1",18,new Date()));
list.add(new User("zhangsan2",23,new Date()));
list.add(new User("zhangsan3",25,new Date()));
list.add(new User("zhangsan4",30,new Date()));
list.add(new User("zhangsan5",36, new Date())); //通过工具类创建writer,默认创建xls格式
ExcelWriter writer = ExcelUtil.getWriter(); //自定义标题名
writer.addHeaderAlias("name","姓名");
writer.addHeaderAlias("age","年龄");
writer.addHeaderAlias("birthday","生日"); // 合并单元格后的标题行,使用默认标题样式
writer.merge(3,"申请人员信息"); //一次性写出内容,使用默认样式,强制输出标题
//Iterable<?> data
writer.write(list,true); //response为HttpServeltReponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8"); //弹出下载对话框的文件名,不能为中文,中文请自行编码 String name = "申请学院";
try {
name = URLEncoder.encode(name, StandardCharsets.UTF_8.toString());
response.setHeader("Content-Disposition","attachment;filename="+name+".xls");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} ServletOutputStream out= null;
try{
out = response.getOutputStream();
writer.flush(out,true); }catch (IOException e){
e.printStackTrace();
}finally {
//关闭writer,释放内存
writer.close();
}
IoUtil.close(out); } //上传并解析数据
@PostMapping("/upload")
@ResponseBody
public String upload(@RequestParam("file") MultipartFile multipartFile) {
String suffex = multipartFile.getOriginalFilename().split("\\.")[1]; if (!"xlsx".equals(suffex)) {
return "导入失败,只支持xlsx文件上传";
}
if (Objects.isNull(multipartFile)) {
return "导入失败,上传文件为空";
}
//得到文件流
InputStream inputStream = null;
StringBuffer errMsg = new StringBuffer("");
try {
inputStream = multipartFile.getResource().getInputStream(); String[] head={"用户账号","用户姓名","部门代码","部门名称"};
String[] headerAlias={"username","realName","deptCode","deptName"}; ExcelReader reader = ExcelUtil.getReader(inputStream);
List<Object> header=reader.readRow(0);
//替换表头关键字
if(ArrayUtils.isEmpty(head)||ArrayUtils.isEmpty(headerAlias)||head.length!=headerAlias.length){
return null;
}else{
for(int i=0;i<head.length;i++){
if(head[i].equals(header.get(i))){
reader.addHeaderAlias(head[i],headerAlias[i]);
}else{
return null;
}
}
}
//读取指点行开始的表数据(以下介绍的三个参数也可以使用动态传入,根据个人业务情况修改)
//1:表头所在行数 2:数据开始读取位置 Integer.MAX_VALUE:数据读取结束行位置
List<Map<String,Object>> read = reader.read(0,1,Integer.MAX_VALUE);
System.out.println(read);
} catch (Exception e) {
System.out.println(e.getMessage());
IoUtil.close(inputStream);
}
if (errMsg.length() > 0) {
return errMsg.toString() + "行数据导入失败,其余导入成功.";
}
return "导入成功";
} //上传excle并且把错误的数据标识出来
@PostMapping("/uploadAndCheck")
@ResponseBody
public String uploadAndCheck(@RequestParam("file") MultipartFile multipartFile,HttpServletResponse response) {
String suffex = multipartFile.getOriginalFilename().split("\\.")[1];
int correctNum = 0 ;
int wrongNum = 0;
if (!"xlsx".equals(suffex)) {
return "导入失败,只支持xlsx文件上传";
}
if (Objects.isNull(multipartFile)) {
return "导入失败,上传文件为空";
}
//得到文件流
InputStream inputStream = null;
StringBuffer errMsg = new StringBuffer("");
try {
inputStream = multipartFile.getResource().getInputStream(); String[] head={"用户账号","用户姓名","部门代码","部门名称"};
String[] headerAlias={"username","realName","deptCode","deptName"}; ExcelReader reader = ExcelUtil.getReader(inputStream);
List<Object> header=reader.readRow(0);
//替换表头关键字
if(ArrayUtils.isEmpty(head)||ArrayUtils.isEmpty(headerAlias)||head.length!=headerAlias.length){
return null;
}else{
for(int i=0;i<head.length;i++){
if(head[i].equals(header.get(i))){
reader.addHeaderAlias(head[i],headerAlias[i]);
}else{
return null;
}
}
}
//读取指点行开始的表数据(以下介绍的三个参数也可以使用动态传入,根据个人业务情况修改)
//1:表头所在行数 2:数据开始读取位置 Integer.MAX_VALUE:数据读取结束行位置
List<Map<String,Object>> read = reader.read(0,1,Integer.MAX_VALUE);
int size = read.size(); List<Temp> list= new ArrayList<Temp>();
for(int i=0; i<size; i++){
Map map = read.get(i);
String username = map.get("username").toString();
String realName = map.get("realName").toString();
String deptCode = map.get("deptCode").toString();
String deptName = map.get("deptName").toString(); //假设该条数据中部门编码长度不符合标准
if(deptCode.length()>3){
String text = "1,部门编码长度不对";
list.add(new Temp(username,realName,deptCode,deptName,text));
wrongNum ++;
}
}
correctNum = size - wrongNum;
System.out.println(read); //生成错误数据的excle begin
//通过工具类创建writer,默认创建xls格式
ExcelWriter writer = ExcelUtil.getWriter(); writer.addHeaderAlias("username","用户账号");
writer.addHeaderAlias("realName","用户姓名");
writer.addHeaderAlias("deptCode","部门代码");
writer.addHeaderAlias("deptName","部门名称");
writer.addHeaderAlias("text","错误提示"); // 合并单元格后的标题行,使用默认标题样式
writer.merge(4,"错误数据列表"); //一次性写出内容,使用默认样式,强制输出标题
//Iterable<?> data
writer.write(list,true); //response为HttpServeltReponse对象
response.setContentType("application/vnd.ms-excel;charset=utf-8"); //弹出下载对话框的文件名,不能为中文,中文请自行编码
String name = "excleWrong";
try {
name = URLEncoder.encode(name, StandardCharsets.UTF_8.toString());
response.setHeader("Content-Disposition","attachment;filename="+name+".xls"); } catch (UnsupportedEncodingException e) {
e.printStackTrace();
} ServletOutputStream out= null;
try{
out = response.getOutputStream();
writer.flush(out,true); }catch (IOException e){
e.printStackTrace();
}finally {
//关闭writer,释放内存
writer.close();
}
IoUtil.close(out);
//生成错误数据的excle end } catch (Exception e) {
System.out.println(e.getMessage());
IoUtil.close(inputStream);
}
if (errMsg.length() > 0) {
return errMsg.toString() + "行数据导入失败,其余导入成功.";
}
System.out.println("导入成功数据"+correctNum+"条,错误数据"+wrongNum+"条,错误数据请下载修改后重新上传!");
return "导入成功数据"+correctNum+"条,错误数据"+wrongNum+"条,错误数据请下载修改后重新上传!"; } }
注:
1、 Controller 中downloadExcel方法里模板的存放路径

2、Controller 中upload方法中上传文件的内容

3、Controller 中uploadAndCheck方法中上传文件的内容和让用户下载数据格式有问题的数据
上传文件与第二步的相同
让用户下载数据格式有问题的数据如下:


java对excle操作:下载、上传以及上传中错误数据动态生成excle给用户下载的更多相关文章
- java的io操作(将字符串写入到txt文件中)
import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java ...
- java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息
1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...
- Java实现FTP文件与文件夹的上传和下载
Java实现FTP文件与文件夹的上传和下载 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于Internet上的控制 ...
- java的poi技术下载Excel模板上传Excel读取Excel中内容(SSM框架)
使用到的jar包 JSP: client.jsp <%@ page language="java" contentType="text/html; charset= ...
- java web 能够实现整个文件夹的上传下载吗?
在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...
- 从.Net到Java学习第十篇——Spring Boot文件上传和下载
从.Net到Java学习系列目录 图片上传 Spring Boot中的文件上传就是Spring MVC中的文件上传,将其集成进来了. 在模板目录创建一个新的页面 profile/uploadPage. ...
- 需求-java web 能够实现整个文件夹的上传下载吗?
我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...
- 文件上传和下载(可批量上传)——Spring(三)
在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt ...
- 文件上传和下载(可批量上传)——Spring(二)
针对SpringMVC的文件上传和下载.下载用之前“文件上传和下载——基础(一)”的依然可以,但是上传功能要修改,这是因为springMVC 都为我们封装好成自己的文件对象了,转换的过程就在我们所配置 ...
- Struts2实现文件上传和下载,多文件上传,限制文件大小,限制文件类型
文件上传使用的包:commons-upload-xx.jar commons-io-xx.jar 一.实现文件上传: 1.在表单空间中添 ...
随机推荐
- jmeter-json断言
1.JSON 断言所在位置:断言->JSON 断言 2.JSON断言中的字段解析 Assert JSON Path exists:json 表达式,判断所字段是否存在,存在则为True, 否则为 ...
- [GDOI22pj1A] 邹忌讽秦王纳谏
时间空间限制: 1 秒, 256 MB 齐国人邹忌对齐国国君齐威王说,大王身边的人会因为私情.利益等原因而对大王阿谀奉承,所以不能光听好话,只有广泛接受群众的批评意见,才不会被蒙蔽双眼,齐国才能强盛. ...
- LR(0)分析法
LR(0)是一种自底向上的语法分析方法.两个基本动作是移进和规约. 具体例子如下 已知文法G[E] (1) E→aА (2) E→bB (3) A→cА (4) A→d (5) B→cB (6) B→ ...
- 【C#】【IO】【实例】统计多个文件夹下的图片
因工作需要繁琐的进行同一目录多个文件夹下的图片统计,便使用代码来解决. 需求:统计的是多少个文件夹包含了图片,并非是统计有多少张图. 我们先用Python来创建一个现场环境(巩固巩固py知识): 1 ...
- ASR项目实战-前处理
本文深入探讨前处理环节. 首先介绍一些基本的名词,比如 文件名后缀 文件格式 音频格式 采样率和位深 预备知识 文件名后缀.文件格式和音频格式 常见的音频文件,比如.wav..mp3..m4a..wm ...
- 多项式(Poly)笔记
开头先扔板子:多项式板子们 定义 多项式(polynomial)是形如 \(P(x) = \sum \limits_{i = 0}^{n} a_i x ^ i\) 的代数表达式.其中 \(x\) 是一 ...
- 使用openfrp搭建网站[无公网ip]
使用openfrp搭建网站的理由 免费/低成本 安全 可扩展 使用条件 有一台低功耗准系统/服务器[无公网ip] u盘 网线/waif网卡 屏幕 使用方法 第1步准备服务 低功耗准系统 / 服务器 推 ...
- 一行代码解决Three.js中只能在一侧看到物体的问题
项目场景: 因为该项目比较复杂庞大,在此就简单介绍一下: 通过Three.js创建若干个物体进行了组装,从而形成了一个类似眼球模拟模型的项目,用户可以通过拖动鼠标来达到控制视角(摄像机)的目的 ...
- CUDA个人入坟笔记
CUDA是建立在NVIDIA的GPUs上的一个通用并行计算平台和编程模型,基于CUDA编程可以利用GPUs的并行计算引擎来更加高效地解决比较复杂的计算难题.近年来,GPU最成功的一个应用就是深度学习领 ...
- 7、Flutter GridView网格布局组件(遍历)
GridView创建网格列表主要有下面三种方式 1.可以通过GridView.count 实现网格布局 一行的 Widget 数量 class HomePage extends Stateles ...