网上很多下载导出功能都需要先在本机生成文件,然后通过下载流进行下载,最后再删除临时文件。但是有些公司对文件生成有权限要求或者禁止生成临时文件,这个时候,这些代码就不能用了。这里我给大家提供一种新的方法来进行下载导出。
首先,先来造一批模拟数据,这里就不走数据库了,主要演示导出功能。
//模拟导出数据
List statusList = new ArrayList<>();
for (int i=1; i<=100000; i++) {
Status status = new Status();
status.setId("" + i + "");
status.setName("第" + i + "条");
status.setValue("第" + i + "条内容");
status.setMark("第" + i + "条备注");
status.setCrateTime(sdf.format(new Date()));
statusList.add(status);
}
然后是生成要导出的zip压缩包的字节数组流。
String[] fieldNames = new String[]{"id", "name", "value", "mark", "crateTime"};
//筛选条件中文
String[] fieldDescs = new String[]{"编号", "名称", "内容", "备注", "创建时间"};
ByteArrayOutputStream output = exportService.exportData(statusList, fieldNames, fieldDescs);
在zip压缩包的流中加入csv格式excel文件的字节数组流。
@Override
public ByteArrayOutputStream exportData(List statusList, String[] fieldNames, String[] fieldDescs) {
StopWatch stopWatch = new StopWatch();
stopWatch.start("生成csv byte数组数据");
//csv文件名前缀
String fileNameStr = "统计导出";
//生成byte数组
byte[] bytes = this.generateCsvFile(statusList, fieldNames, fieldDescs);
stopWatch.stop();
//打包zip文件;
stopWatch.start("压缩数据到下载流");
ByteArrayOutputStream temp = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(temp);
try {
String entryName = fileNameStr + ".csv";
ZipEntry entry = new ZipEntry(entryName);
zos.putNextEntry(entry);
zos.write(bytes);
zos.closeEntry();
zos.close();
stopWatch.stop();
log.info(stopWatch.prettyPrint());
return temp;
} catch (Exception e) {
log.error("zip文件生成错误。", e);
} finally {
try {
if (zos != null) {
zos.close();
}
if (temp != null) {
temp.close();
}
} catch (IOException e) {
log.error("文件流关闭错误。", e);
}
}
return null;
}
下面是csv字节数组流的生成代码。
/**
* 传入数据列表、目标文件、字段名和字段标题,生成csv文件
*
* @param dataList
* @param fieldNames
* @param fieldDescs
* @return
*/
public byte[] generateCsvFile(List dataList, String[] fieldNames, String[] fieldDescs) {
StopWatch stopWatch = new StopWatch();
stopWatch.start("生成csv");
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream)
) {
//文件头部插入excel的BOM信息,否则打开会中文乱码
bufferedOutputStream.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
//插入标题行
writeRow(fieldDescs, bufferedOutputStream);
String[] contents = new String[fieldNames.length];
if (dataList.get(0) instanceof Map) {
for (int i = 0; i < dataList.size(); i++) {
Map dataMap = (HashMap) dataList.get(i);
for (int j = 0; fieldNames != null && j < fieldNames.length; j++) {
String filedName = fieldNames[j];
Object obj = dataMap.get(filedName);
if (obj == null || "null".equals(String.valueOf(obj))) {
obj = "";
}
contents[j] = String.valueOf(obj);
}
writeRow(contents, bufferedOutputStream);
}
} else if (dataList.get(0) instanceof BaseEntity) {
for (int i = 0; i < dataList.size(); i++) {
Class clazz = dataList.get(i).getClass();
for (int j = 0; fieldNames != null && j < fieldNames.length; j++) {
String filedName = toUpperCaseFirstOne(fieldNames[j]);
Method method = clazz.getMethod(filedName);
method.setAccessible(true);
Object obj = method.invoke(dataList.get(i));
if (obj == null || obj.equals("null")) {
obj = "";
}
contents[j] = String.valueOf(obj);
}
writeRow(contents, bufferedOutputStream);
}
}
bufferedOutputStream.flush();
return byteArrayOutputStream.toByteArray();
} catch (UnsupportedEncodingException e) {
log.error("UnsupportedEncodingException ", e);
} catch (Exception e) {
log.error("未捕获异常。", e);
} finally {
stopWatch.stop();
log.info(stopWatch.prettyPrint());
}
return null;
}
最后导出生成的zip压缩包的字节数组流到客户端。
byte[] content = output.toByteArray();
InputStream is = new ByteArrayInputStream(content);
//下载文件
String fileName = new Date().getTime() + ".zip";
try {
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
ServletOutputStream out = response.getOutputStream();
// 设置response参数,可以打开下载页面
response.reset();
response.setContentType("application/vnd.ms-excel;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes(), "iso-8859-1"));
try {
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(out);
byte[] buff = new byte[2048];
int bytesRead;
// Simple read/write loop.
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
} catch (final IOException e) {
throw e;
} finally {
if (bis != null)
bis.close();
if (bos != null)
bos.close();
stopWatch.stop();
log.info(stopWatch.prettyPrint());
}
} catch (Exception e) {
e.printStackTrace();
}
大功告成。具体有不清楚的,可以去我的github看看。地址:
https://github.com/whol/exportdemo,分支为 简单查询生成单csv文件并打包下载
最后修改于 2019-04-01 15:30:12
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付

