当时导入的时候用的openCsv,那么导出的时候自然也是用这个,查了好多资料才找到解决方案,下面记录一下实现过程。

1.Controller层:

/**
* 导出csv文件
*/
@RequestMapping("/exportcsv")
@RequiresPermissions("xxx:xxxx:xxx")
public String exportCsv(@RequestBody List<xxxEntity> exportResults, HttpServletResponse response) {
return xxxService.exportCsvFile(exportResults, response);
}

2.实现类部分:

@Override
public String exportCsvFile(List<xxxEntity> exportResults, HttpServletResponse response) {
try {
CSVUtils<xxxEntity> xxx = new CSVUtils();
xxx.generateCsvFile(exportResults, "exportResults.csv", HEADER);
xxx.readCsvFileStream("exportResults.csv", response);
} catch (IOException | CsvDataTypeMismatchException | CsvRequiredFieldEmptyException e) {
log.error("EXPORT ERROR", e);
}
return null;
}

3.核心Util导出方法:

import com.opencsv.CSVWriter;
import com.opencsv.bean.StatefulBeanToCsv;
import com.opencsv.bean.StatefulBeanToCsvBuilder;
import com.opencsv.exceptions.CsvDataTypeMismatchException;
import com.opencsv.exceptions.CsvRequiredFieldEmptyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List; /**
* CSV 工具类
*
* @author jing
*/
@Slf4j
@Component
public class CSVUtils<T>{ /**
* 将前台传递的数据生成csv文件
* @param exportResults
* @param fileName
* @param header
* @throws IOException
* @throws CsvDataTypeMismatchException
* @throws CsvRequiredFieldEmptyException
*/
public static<T> void generateCsvFile(List<T> exportResults, String fileName, String[] header) throws IOException, CsvDataTypeMismatchException, CsvRequiredFieldEmptyException {
Writer writer = new FileWriter(fileName);
// 写表头
CSVWriter csvWriter = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER, CSVWriter.NO_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
csvWriter.writeNext(header);
//写内容
StatefulBeanToCsv beanToCsv = new StatefulBeanToCsvBuilder(writer).build();
beanToCsv.write(exportResults);
csvWriter.close();
writer.close();
} /**
* 读取csv文件流返回前端下载
* @param fileName
* @param response
* @throws UnsupportedEncodingException
*/
public static void readCsvFileStream(String fileName, HttpServletResponse response) throws UnsupportedEncodingException {
String myFileName = new String(fileName.getBytes("utf-8"), "gbk");
File file = new File(myFileName);
if (file.exists()) {
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + myFileName);// 设置文件名
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
if(file.delete()){
log.error(file.getName() + " 文件已被删除!");
}else{
log.error("文件删除失败!");
}
} }

这里的思路是后端接收前端发来的list,然后利用openCsv写入生成csv文件,再从csv文件中读取文件流返回前端下载。

下面是项目中的两个问题:

1.如果不指定csv文件中的顺序,那么他是基于列名升序排列,那么这里就需要用@CsvBindByPosition(position = 0)来定位位置,但是如果你用这个来定位的话,那么表头就展示不出来,如果@CsvBindByName的话,又定位不了位置,那么这里我的解决方案就是,用@CsvBindByPosition(position = 0)来定位位置,表头的话再自己写入。

2.如果列中出现了时间相关的数据,那么他展示的数据是GMT+8这种格式,这时候的解决方案是用@CsvDate("yyyy-MM-dd HH:mm:ss")来进行时间格式化。

我的实体类大概长这样儿:

/**
* 用户
*/
@Data
@TableName("user")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L; @TableId
@CsvBindByPosition(position = 0)
private Long id;
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
@CsvBindByPosition(position = 1)
private String userName;
/**
* 创建时间
*/
@CsvBindByPosition(position = 2)
@CsvDate("yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
* 修改时间
*/
@CsvBindByPosition(position = 3)
@CsvDate("yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@TableField(fill = FieldFill.UPDATE)
private Date updateTime;
}

这中导出方式需要有一个中间文件csv的生成,如果有更好的方法,欢迎评论区留言。

Java之利用openCsv导出csv文件的更多相关文章

  1. 应用Java泛型和反射导出CSV文件

    项目中有需求要把数据导出为CSV文件,因为不同的类有不同的属性,为了代码简单,应用Java的泛型和反射,写了一个函数,完成导出功能. public <T> void saveFile(Li ...

  2. java opencsv解析csv文件

    记一次使用opencsv解析csv文件时碰到的坑 最近在开发过程中需要解析csv文件,公司用的解析工具是opencsv,在根据opencsv的官方文档去解析时发现csv文件中含有繁体字,使用其自带的C ...

  3. Spring Boot下的一种导出CSV文件的代码框架

    1.前言 ​ CSV,逗号分隔值(Comma-Separated Values),即为逗号分隔的文本文件.如果值中含有逗号.换行符.制表符(Tab).单引号及双引号,则需要用双引号括起来:如果值中包含 ...

  4. PHP导出CSV文件

    经常会碰到需要从数据库中导出数据到Excel文件,用一些开源的类库,比如PHPExcel,确实比较容易实现,但对大量数据的支持很不好,很容易到达PHP内存使用上限.这里的方法是利用fputcsv写CS ...

  5. 导出csv文件示例

    导出csv文件示例 csv文件默认以英文逗号,做为列分隔符换行符\n作为行分隔符,写入到一个.csv文件即可.含有英文逗号,和换行符会发生数据输出会出现混乱,下面列出一些处理方法.特殊字符处理1.含有 ...

  6. mysql SQLyog导入导出csv文件

    1.选择数据库表 --> 右击属性 --> 备份/导出 --> 导出表数据作为 --> 选择cvs --> 选择下面的“更改” --> 字段 --> 变量长度 ...

  7. PHP 读取/导出 CSV文件

    工作中经常会有遇到导入/导出的需求,下面是常用的方法.读取CSV文件,可以分页读取,设置读取行数,起始行数即可.导出CSV文件,用两种方法进行实现. /** * 读取CSV文件 * @param st ...

  8. Web 端 js 导出csv文件(使用a标签)

    前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...

  9. PHP导出CSV文件出现乱码的解决方法

    在做项目时碰到使用外语的情况下,我们就会使用UTF-8编码.但是,在用PHP导出CSV文件时,如果写入的数据是使用UTF-8编码的日语.韩语之类的外文,就会出现乱码. 要解决PHP生成CSV文件的乱码 ...

  10. [转]PL/SQL Developer 导入导出csv文件

    PL/SQL Developer 可以导入或者导出CSV文件. 导入CSV文件步骤: 1.选择tools->text importer.... 2.选择第二个Data to oracle选项卡, ...

随机推荐

  1. 基于.NetCore开发博客项目 StarBlog - (30) 实现评论系统

    前言 时隔五个月,终于又来更新 StarBlog 系列了~ 这次是呼声很大的评论系统. 由于涉及的代码量比较大,所以本文不会贴出所有代码,只介绍关键逻辑,具体代码请同学们自行查看 GitHub 仓库. ...

  2. 如何使用 Helm 在 K8s 上集成 Prometheus 和 Grafana|Part 1

    本系列将分成三个部分,您将学习如何使用 Helm 在 Kubernetes 上集成 Prometheus 和 Grafana,以及如何在 Grafana 上创建一个简单的控制面板.Prometheus ...

  3. bash shell笔记整理——date命令

    date命令初步了解 简单来说date的主要作用大多数用于以给定的格式来显示时间. 在后期我们写一些脚本当中也会使用到,比如说按照日期来给文件备份打包等. 下面我们来看看帮助信息: [root@ngi ...

  4. Java多线程学习(Day01)

    目录 线程简介 线程实现(重点) 线程状态 线程同步(重点) 线程通信问题 进程与线程概念 --来自百度百科的解释: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资 ...

  5. python 获取android 应用使用情况

    python 获取android 应用使用情况 本文主要讲述python 脚本获取android 应用使用情况. 主要思路:使用adb 获取当前activity ,1s 一次输出. 主要涉及知识点: ...

  6. 【docker】docker中装Redis集群

    一.搭建步骤 1.启动容器 #关闭防火墙 systemctl start docker 2.新建6个docker容器redis实例 docker run -d --name redis-node-1 ...

  7. JavaFx之ScrollPane滚动板面、CheckBox复选框(二十四)

    JavaFx之ScrollPane滚动板面.CheckBox复选框(二十四) 多个复选框时可能会超出屏幕,需要使用滚动版面. 布局方式:ScrollPane包括VBox.VBox 包括多个 Check ...

  8. Spring Eureka 源码解析

    本文将简要分析一下关于 Spring Eureka 相关的一些必要的源代码,对应的版本:Spring Cloud 2021.0.1 @EnableEurekaServer 注解 @EnableEure ...

  9. 一些JavaSE学习过程中的思路整理(三)(主观性强,持续更新中...)

    目录 一些JavaSE学习过程中的思路整理(三)(主观性强,持续更新中...) Java线程同步的几种常见情况分析 由简单到复杂的几种单例模式写法 死锁的实现与破解 使用lambda表达式化简代码 J ...

  10. ElasticSearch-1

    原文链接:https://gaoyubo.cn/blogs/52ef5bf7.html 一.Elasticsearch 架构设计 Elasticsearch 架构层: Elasticsearch 五层 ...