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.在表单空间中添 ...
随机推荐
- jdk21的外部函数和内存API(MemorySegment)(官方翻译)
1.jdk21: 引入一个 API,通过该 API,Java 程序可以与 Java 运行时之外的代码和数据进行互操作.通过有效地调用外部函数(即JVM外部的代码)和安全地访问外部内存(即不由JVM ...
- django查询-列延迟加载only()、defer()
这玩意和sqlalchemy的几乎一样. only():只加载给定的列,其他列只有在使用时会发起二次查询 defer():不加载指定的列,刚好和only()相反. 实例: >>> r ...
- 聊聊流式数据湖Paimon(二)
当前的问题 Apache Paimon 最典型的场景是解决了 CDC (Change Data Capture) 数据的入湖:CDC 数据来自数据库.一般来说,分析需求是不会直接查询数据库的. 容易对 ...
- C++ Qt开发:Charts绘制各类图表详解
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TreeWid ...
- 2024-01-06:用go语言,在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧 在桥上有一些石子,青蛙很讨厌踩在这些石子上 由于桥的长度和青蛙一次跳过的距离都是正整数 我们可以把独木桥
2024-01-06:用go语言,在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧 在桥上有一些石子,青蛙很讨厌踩在这些石子上 由于桥的长度和青蛙一次跳过的距离都是正整数 我们可以把独木桥 ...
- JavaImprove--Lesson04--LocalDateTime,ZoneId,Instant,DateTimeFormatter
一.LocalDateTime LocalDateTime是JDK8的新时间特性,它解决了Date类和Calender类的很多不足,如使用不方便,线程不安全,以及获取时间戳只能拿到毫秒而不能拿到纳秒等 ...
- maven系列:POM文件总体配置说明
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- Boost程序库完全开发指南:1.1-C++基础知识点梳理
主要整理了N多年前(2010年)学习C++的时候开始总结的知识点,好长时间不写C++代码了,现在LLM量化和推理需要重新学习C++编程,看来出来混迟早要还的. 1.shared_ptr 解析:sh ...
- CUDA C编程权威指南:1.2-CUDA基础知识点梳理
主要整理了N多年前(2013年)学习CUDA的时候开始总结的知识点,好长时间不写CUDA代码了,现在LLM推理需要重新学习CUDA编程,看来出来混迟早要还的. 1.闭扫描和开扫描 对于一个二元 ...
- 云图说 | MSSI之应用业务模型ABM,搭建业务与技术的数据治理桥梁
摘要:应用业务模型ABM(Application Business Model)是MSSI为客户提供的统一模型管理服务. 本文分享自华为云社区<[云图说] | 第274期 MSSI之应用业务模型 ...