工作中经常遇到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给用户下载的更多相关文章

  1. java的io操作(将字符串写入到txt文件中)

    import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java ...

  2. java使用Jsch实现远程操作linux服务器进行文件上传、下载,删除和显示目录信息

    1.java使用Jsch实现远程操作linux服务器进行文件上传.下载,删除和显示目录信息. 参考链接:https://www.cnblogs.com/longyg/archive/2012/06/2 ...

  3. Java实现FTP文件与文件夹的上传和下载

    Java实现FTP文件与文件夹的上传和下载 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为"文传协议".用于Internet上的控制 ...

  4. java的poi技术下载Excel模板上传Excel读取Excel中内容(SSM框架)

    使用到的jar包 JSP: client.jsp <%@ page language="java" contentType="text/html; charset= ...

  5. java web 能够实现整个文件夹的上传下载吗?

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用 ...

  6. 从.Net到Java学习第十篇——Spring Boot文件上传和下载

    从.Net到Java学习系列目录 图片上传 Spring Boot中的文件上传就是Spring MVC中的文件上传,将其集成进来了. 在模板目录创建一个新的页面 profile/uploadPage. ...

  7. 需求-java web 能够实现整个文件夹的上传下载吗?

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...

  8. 文件上传和下载(可批量上传)——Spring(三)

    在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt ...

  9. 文件上传和下载(可批量上传)——Spring(二)

    针对SpringMVC的文件上传和下载.下载用之前“文件上传和下载——基础(一)”的依然可以,但是上传功能要修改,这是因为springMVC 都为我们封装好成自己的文件对象了,转换的过程就在我们所配置 ...

  10. Struts2实现文件上传和下载,多文件上传,限制文件大小,限制文件类型

    文件上传使用的包:commons-upload-xx.jar                                 commons-io-xx.jar 一.实现文件上传: 1.在表单空间中添 ...

随机推荐

  1. 详细一些的vue生命周期

    如果你和我一样,以前对vue生命周期的理解仅限于生命周期钩子,那么本文可以让我们更深入一层,理解vue在生命周期各个阶段所做的事,对我们对vue的理解和使用很有好处. (1)通过new Vue()创建 ...

  2. HttpClient报错Timeout waiting for connection from pool

    报错现象 线上项目使用HttpClient请求第三方的HTTP资源,并发量高的时候,日志框报Timeout waiting for connection from pool 客户端的现象是有时正常,有 ...

  3. tryhackme进攻性渗透测试-Advanced Exploitation 高级利用

    Steel Mountain 侦察 Nmap -sC -sV -O $IP -oN basic_scan.nmap Nmap -script=vuln $IP -oN vuln_scan.nmap 总 ...

  4. 循环依赖导致编译或者服务启动报错问题:The dependencies of some of the beans in the application context form a cycle

    错误如图: 我的是服务器启动服务时报错: ***************************APPLICATION FAILED TO START************************* ...

  5. Chrome扩展开发系列开篇

    大家好,我是 dom 哥.这是我关于 Chrome 扩展开发的系列文章,感兴趣的可以 点个小星星. 浏览器现状 研究机构 Statcounter 发布了 2023 年 9 月报告,揭示了有关浏览器的最 ...

  6. 基于一维卷积神经网络模型的AI量化智能选股策略

    这是早前BigQuant专题研究:基于卷积神经网络CNN的深度学习因子选股模型.卷积神经网络(Convolutional Neural Network, CNN),是计算机视觉研究和应用领域中最具影响 ...

  7. iMessage群发,iMessage群发基础知识,iMessage群发源代码分享

    在当今的数字化时代,即时通讯已经成为我们日常生活和工作中不可或缺的一部分,其中,苹果的iMessage服务因其出色的用户体验和无缝的设备间同步而备受用户喜爱. 然而,你是否想过如何利用iMessage ...

  8. 春秋云镜 - CVE-2022-32991

    靶标介绍: 该CMS的welcome.php中存在SQL注入攻击. 访问页面,先注册,使用邮箱加密码登录. bp抓包,后台挂上sqlipy然后去测welcome.php,常用的语句都没成功但过一会就有 ...

  9. buuctf 加固题 babypython WriteUp

    原题wp参考链接:https://www.cnblogs.com/karsa/p/13529769.html 这是CISCN2021 总决赛的题,解题思路是软链接zip 读取文件,然后伪造admin的 ...

  10. 遍历菜单树得到所有菜单ids

    1.前言 在我们实现菜单管理页面的时候,有时候我们需要默认展开所有的菜单列表,但是因为后端有时候没有返回所有菜单ids数组. 而且我们也不容易获取到所有菜单ids,比如如果我们通过角色id查询到所有菜 ...