准备工作
加入依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
代码
package com.jake.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author wengzhengkai
*/
@Slf4j
public class CommonCSVUtils {
public static final String CSV_FILE_SUFFIX = ".csv";
public static final String DEFAULT_CHARACTER_ENCODING = "UTF-8";
/**
* @param heads 表头
* @param records 记录
* @param filename 文件名
* @param response 响应
*/
public static void download(String[] heads, List<List<String>> records,
String filename, HttpServletResponse response) {
if (!StringUtils.endsWithIgnoreCase(filename, CSV_FILE_SUFFIX)) {
filename = filename + CSV_FILE_SUFFIX;
}
CSVPrinter printer = null;
PrintWriter writer = null;
response.setCharacterEncoding(DEFAULT_CHARACTER_ENCODING);
response.setContentType("text/csv;charset=" + DEFAULT_CHARACTER_ENCODING);
try {
response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
"attachment;filename=\"" + URLEncoder.encode(filename, DEFAULT_CHARACTER_ENCODING) + "\"");
log.info("下载的 csv 文件名为 {}", filename);
} catch (UnsupportedEncodingException e) {
log.error("不支持的编码方式");
}
try {
// 创建表头,并以换行符分割记录
CSVFormat format = CSVFormat.DEFAULT.withRecordSeparator(StringUtils.LF).withHeader(heads);
writer = response.getWriter();
// 防止乱码
writer.write(new String(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF}, StandardCharsets.UTF_8));
printer = new CSVPrinter(writer, format);
// 写入 csv 内容
for (List<String> record : records) {
printer.printRecord(record);
}
} catch (IOException e) {
log.error("创建临时 CSV 文件时出错", e);
} finally {
try {
if (printer != null) {
printer.flush();
printer.close();
}
if (writer != null) {
writer.flush();
writer.close();
}
} catch (IOException e) {
log.error("创建临时 CSV 文件后刷出或关闭流时出错");
}
}
}
}
注意该方法的几个参数:
参数 | 说明 |
---|---|
String[] heads | CSV 的表头 |
List<List<String>> records | 记录,其长度与表头一致,内层的 list 表示会以此写入到对应表头下的数据,比如表头为序号、性别、年龄,那么内层的 list 的顺序也应该对应序号、性别、年龄。 |
String filename | 文件名 |
HttpServletResponse response | Http 响应对象,可在其中指定 response 的编码方式、contentType,设置 response 为下载类型等。 |