今天看到需求里面有个需要将数据导成csv文件的格式,这里记录下自己的实现过程。直接上后端代码,这里用的springboot框架实现。
工具类代码下面最下面有一个main方法可直接执行导出功能,你可以用这个测试数据看看效果。
package com.etone.project.utils;
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
public class CsvUtils {
public static final Logger logger = LoggerFactory.getLogger(CsvUtils.class);
/**
* 生成为CVS文件
*
* @param exportData
* 源数据List
* @param map
* csv文件的列表头map
* @param outPutPath
* 文件路径
* @param fileName
* 文件名称
* @return
*/
@SuppressWarnings("rawtypes")
public static File createCSVFile(List exportData, LinkedHashMap map,
String outPutPath, String fileName) {
File csvFile = null;
BufferedWriter csvFileOutputStream = null;
try {
File file = new File(outPutPath);
if (!file.exists()) {
file.mkdir();
}
// 定义文件名格式并创建
csvFile = File.createTempFile(fileName, ".csv",
new File(outPutPath));
logger.debug("csvFile:" + csvFile);
// UTF-8使正确读取分隔符","
csvFileOutputStream = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(csvFile), "GBK"), 1024);
logger.debug("csvFileOutputStream:" + csvFileOutputStream);
// 写入文件头部
for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator
.hasNext();) {
java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator
.next();
csvFileOutputStream
.write("" + (String) propertyEntry.getValue() != null ? (String) propertyEntry
.getValue() : "" + "");
if (propertyIterator.hasNext()) {
csvFileOutputStream.write(",");
}
}
csvFileOutputStream.newLine();
// 写入文件内容
for (Iterator iterator = exportData.iterator(); iterator.hasNext();) {
Object row = (Object) iterator.next();
for (Iterator propertyIterator = map.entrySet().iterator(); propertyIterator
.hasNext();) {
java.util.Map.Entry propertyEntry = (java.util.Map.Entry) propertyIterator
.next();
csvFileOutputStream.write((String) BeanUtils.getProperty(
row, (String) propertyEntry.getKey()));
if (propertyIterator.hasNext()) {
csvFileOutputStream.write(",");
}
}
if (iterator.hasNext()) {
csvFileOutputStream.newLine();
}
}
csvFileOutputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
csvFileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return csvFile;
}
/**
* 下载文件
*
* @param response
* @param csvFilePath
* 文件路径
* @param fileName
* 文件名称
* @throws IOException
*/
public static void exportFile(HttpServletResponse response,
String csvFilePath, String fileName) throws IOException {
// response.setHeader("Content-type", "application-download");
FileInputStream in = null;
OutputStream out = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
response.setContentType("text/csv;charset=UTF-8");
response.setHeader("Content-Disposition", "attachment;filename="
+ URLEncoder.encode(fileName, "UTF-8"));
response.setCharacterEncoding("UTF-8");
try {
in = new FileInputStream(csvFilePath);
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.flush();
} catch (FileNotFoundException e) {
logger.error("获取文件错误!");
} finally {
if (in != null) {
try {
in.close();
out.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
/**
* 导出
*
* @param response
* @param
* @return
* @throws IOException
*/
public static void downloadFile(HttpServletRequest request,
HttpServletResponse response, String uri) throws IOException {
// 获取服务其上的文件名称
File file = new File(uri);
String name = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
+ ".zip";
StringBuffer sb = new StringBuffer();
sb.append("attachment; filename=").append(name);
response.setHeader("Expires", "0");
response.setHeader("Cache-Control",
"must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setContentType("application/x-msdownload;charset=UTF-8");
response.setHeader("Content-Disposition", new String(sb.toString()
.getBytes(), "ISO8859-1"));
// 将此文件流写入到response输出流中
FileInputStream inputStream = new FileInputStream(file);
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int i = -1;
while ((i = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, i);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
/**
* 删除该目录filePath下的所有文件
*
* @param filePath
* 文件目录路径
*/
public static void deleteFiles(String filePath) {
File file = new File(filePath);
if (file.exists()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
files[i].delete();
}
}
}
}
/**
* 删除单个文件
*
* @param filePath
* 文件目录路径
* @param fileName
* 文件名称
*/
public static void deleteFile(String filePath, String fileName) {
File file = new File(filePath);
if (file.exists()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isFile()) {
if (files[i].getName().equals(fileName)) {
files[i].delete();
return;
}
}
}
}
}
/**
* 下载csv文件
* @param path
* @param response
*/
public static void download(String path, HttpServletResponse response) {
try {
// path是指欲下载的文件的路径。
File file = new File(path);
// 取得文件名。
String filename = file.getName();
// 以流的形式下载文件。
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
// 设置response的Header,给文件名进行utf-8编码,不然下载的时候文件名乱码不对
response.addHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode (filename, "UTF-8" ));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(
response.getOutputStream());
response.setContentType("application/vnd.ms-excel;charset=gb2312");
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 测试数据
*
* @param args
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main(String[] args) {
List exportData = new ArrayList<Map>();
Map row1 = new LinkedHashMap<String, String>();
row1 = new LinkedHashMap<String, String>();
row1.put("1", "11");
row1.put("2", "12");
row1.put("3", "13");
row1.put("4", "14");
exportData.add(row1);
row1.put("1", "11");
row1.put("2", "12");
row1.put("3", "13");
row1.put("4", "14");
exportData.add(row1);
LinkedHashMap map = new LinkedHashMap();
map.put("1", "第一列");
map.put("2", "第二列");
map.put("3", "第三列");
map.put("4", "第四列");
String path = "E:/export/";
String fileName = "文件导出";
File file = CsvUtils.createCSVFile(exportData, map, path, fileName);
String fileName2 = file.getName();
logger.debug("文件名称:" + fileName2);
}
}
@RestController
@RequestMapping("/dtracejobinfo")
public class DtraceJobInfoController {
public static final Logger logger = LoggerFactory.getLogger(DtraceJobInfoController.class);
@Autowired
public IDtraceJobInfoManager iDtraceJobInfoManager;
//导出图层为csv文件
@RequestMapping(value = "/exportDtraceJob", method = RequestMethod.POST)
public Object exportDtraceJob(@RequestParam(value = "jobName", required = false) String jobName, HttpServletResponse response) {
Map<String, Object> result = new HashMap<String, Object>();
result.put("status", "000");
result.put("message", "操作成功!");
try {
if(StringUtils.isBlank(jobName)){
result.put("status", "999");
result.put("message", "操作失败,jobName值不能为空!");
return result;
}
QueryCriteria criteria = new QueryCriteria();
criteria.put("jobName", jobName);
//根据任务名称查询出对应的file_md5的值,然后根据file_md5值去dtrace_job_file_info表里面查询出对应的值
Map<String, Object> dtraceJob = iDtraceJobInfoManager.getByDtraceJobName(criteria);
System.out.println("=============="+dtraceJob.get("dtrace_file_id"));
if(dtraceJob.get("dtrace_file_id")==null){
result.put("status", "999");
result.put("message", "操作失败,当前任务dtrace_file_id值为空,无法下载!");
return result;
}
criteria.put("fileMd5", dtraceJob.get("dtrace_file_id").toString());
//因架构差异这里返回的一般是一个对象
List<Map<String, Object>> list =iDtraceJobInfoManager.exportDtraceJob(criteria);
//下面代码是重点,参考下面代码
//设置第一列列名
LinkedHashMap map = new LinkedHashMap();
map.put("1", "st_astext");
List exportData = new ArrayList<Map>();
Map row1 = new LinkedHashMap<String, String>();
for (Map<String, Object> mapList : list) { // 执行导出操作
//System.out.println("经纬度值="+mapList.get("st_astext").toString());
row1 = new LinkedHashMap<String, String>();
row1.put("1", mapList.get("st_astext").toString());
exportData.add(row1);
}
//设置导出路径,本地测试用这个地址
String path = "E:/export/";
//线上放到linux服务器的时候用下面地址
//String path = "/data/export/";
//设置导出文件名
String fileName = jobName;
File file = CsvUtils.createCSVFile(exportData, map, path, fileName);
String fileName2 = file.getName();
logger.debug("文件名称:" + fileName2);
//下载到本地
CsvUtils.download(path+fileName2,response);
} catch (Exception e) {
logger.error("操作失败:", e);
result.put("status", "999");
result.put("message", "操作失败!");
}
return result;
}
}
代码执行完后结果如下展示:
这里将代码里面的post请求方式改成get方便你直接用浏览器测试
下载结果如下显示:
然后看本地导出结果:
下载逻辑是先将文件导出后,然后对该文件进行下载。好了,代码实现就到这里面了。