工作中经常遇到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. Codeforces Round 903 (Div. 3)

    Codeforces Round 903 (Div. 3) A. Don't Try to Count 大概题意给你两个字符串a,b.a串可进行的操作为将整个a串复制到之前的a串后面(直接用a+a即可 ...

  2. chatgpt接口开发笔记3: 语音识别接口

    chatgpt接口开发笔记3: 语音识别接口 1.文本转语音 1.了解接口参数 接口地址: POST https://api.openai.com/v1/audio/speech 下面是接口文档描述内 ...

  3. c# 高并发必备技巧(三)

    前面两篇文章主要是介绍了如何解决高并发情况下资源争夺的问题.但是现实的应用场景中除了要解决资源争夺问题,高并发的情况还需要解决更多问题,比如快速处理业务数据等, 本篇文章简要罗列一下与之相关的更多技术 ...

  4. [CF403E]Two Rooted Trees

    Two Rooted Trees 题面翻译 题目描述 你有两棵有根树,每棵树都有 \(n\) 个结点.不妨将这两棵树上的点都用 \(1\) 到 \(n\) 之间的整数编号.每棵树的根结点都是 \(1\ ...

  5. DataGrip给DateTime类型字段赋值当前系统默认时间

    CURRENT_TIMESTAMP alter table 表名 modify column update_time DATETIME NULL DEFAULT CURRENT_TIMESTAMP O ...

  6. Calico IPIP模式下的Cross Subnet特性分析

    本文分享自华为云社区<Calico IPIP模式下的CrossSubnet特性分析>,作者: 可以交个朋友. Calico ipip crossSubnet 模式 Calico-ipip模 ...

  7. xml的语法总结

    xml的语法总结

  8. 劫持 PE 文件:搜索空间缝隙并插入ShellCode

    因近期项目需要弄一款注入型的程序,但多次尝试后发现传统的API都会被安全软件拦截,比如 CreateRemoteThread.SetWindowHookEx.APC.GetThreadContext. ...

  9. C++ 惯用法之 RAII

    RAII(Resource Acquisition Is Initialization)资源获取即初始化,是 C++ 中最基本.应用最广范的惯用法(idiom)之一. RAII 的基本思想是通过构造/ ...

  10. JavaScript异步编程4——Promise错误处理

    目录 1. 概述 2. 详论 3. 参考 1. 概述 在上一篇文章<JavaScript异步编程3--Promise的链式使用>中,通过Promise的链式使用,避免程序中多次嵌套回调(回 ...