文件导出与下载(Excel,Zip)等几种方式

article/2025/8/29 23:33:17

文件下载的几种办法:

1、导出数据为某种格式

​ 这种的话常见的也就是导出为excel格式,个人通常有两种解决办法:

a. 先创建文件,把数据写入文件中去,当然文件也是保存在电脑某个地方的,再读取该文件,以out流的方式再返回出去。

b. 数据量小的情况下,直接返回流,使用response.setHeader(“Content-disposition”,“attachment;filename=”+ URLEncoder.encode(fileName1,“UTF-8”));

实例:

1、导出数据为excel的格式,先按a方法来执行,这里使用最多的一般是Hutools工具包下的excelUtil类。

//可以自己重写一下ExcelUtiil类:public class ExcelUtil {private static final String PATH = "/excel/";private static final String SUFFIX = ".xlsx";// Excel 列宽private static final int COLUMN_WIDTH = 20;@Synchronizedpublic static BigExcelWriter createBigExcelWriter(String fileName , int columnSize){BigExcelWriter bigWriter = cn.hutool.poi.excel.ExcelUtil.getBigWriter(PATH + fileName + SUFFIX);for (int size = columnSize; size >= 0 ;size--){bigWriter.setColumnWidth(size,COLUMN_WIDTH);}return bigWriter;}
}/*** 文件下载*/
public void downloadFIle(Long id,HttpServletRequest request, HttpServletResponse response){// 数据准备,我这里先是在库里查询一下PackageDataTaskPO packageDataTaskPO = packageDataTaskRepository.findPackageById(packageId);String fileName = "";if(ObjectUtil.isNotNull(packageDataTaskPO))fileName = packageDataTaskPO.getPackageName()+"_字段项";// 创建一个Writer流BigExcelWriter bigExcelWriter = com.aamazedata.tax.utils.ExcelUtil.createBigExcelWriter(fileName, 3);List<PackageDataItemPO> packageDataItemPOList = packageDataItemRepository.findAllPackageItemByPackageId(packageId);try {// 获取下Header,判断是哪种浏览器下载文件,来解决文件名的编码命名问题String header = request.getHeader("User-Agent").toUpperCase();if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {fileName = URLEncoder.encode(fileName, "utf-8");fileName = fileName.replace("+", "%20");    //IE下载文件名空格变+号问题} else {fileName = new String(fileName.getBytes(), "UTF8");}// 这里有点重复,为了省事可以不重写上面的ExcelUtils类,因为我写那个类的目的是为了防止数据量很大时,需要提前准备文件,并不是即时写入即时返回String fileName1 = fileName+".xlsx";response.reset();// 设置文件对应后缀的ContentTyperesponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");// 返回的是流的形式response.setContentType("application/octet-stream; charset=utf-8");response.setHeader("Location", fileName1);response.setHeader("Cache-Control", "max-age=0");// 这句的作用是会打开用户那边下载文件时的那个保存位置的框,如果文件名中有中文,建议编下码response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(fileName1, "UTF8"));AtomicInteger count = new AtomicInteger();Map<String, String> head = new HashMap<>();// 开始准备写入数据for(PackageDataItemPO packageDataItemPO:packageDataItemPOList){// 将查询的数据转换为map Map<String, Object> map = getHasSortMap(packageDataItemPO);bigExcelWriter.writeRow(map,count.getAndIncrement() == 0);}bigExcelWriter.close();// 上面的过程就是文件的写入过程并且保存在了/excel/目录下// 下面就是把这个文件读取出来,以流的形式返回File  excelFile= new File("/excel/"+fileName1);FileInputStream fis = new FileInputStream(excelFile);// 文件流上面加一层缓冲流,目的为了加快速度,减少IOBufferedInputStream buff = new BufferedInputStream(fis);// 同理,输出流上也套了一层缓冲的输出流BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());byte[] car = new byte[1024];int l = 0;// 按字节读取文件while (l < excelFile.length()){int j = buff.read(car,0,1024);l += j;// 写入out流中out.write(car,0,j);}// 关闭流fis.close();buff.close();out.close();excelFile.delete();} catch (Exception e) {e.printStackTrace();}
}private Map<String,Object> getHasSortMap(PackageDataItemPO packageDataItemPO){Map<String, Object> map = new HashMap<>(2);map.put("列名",packageDataItemPO.getItemName());map.put("类型",packageDataItemPO.getItemType());return map;}

2、直接输出为流,这里直接使用原生的ExcelUtil工具,并体验复杂Excel的编写

public void downFile(long id,HttpServletResponse response){// 数据准备ExportTaskPO exportTaskPO = exportTaskRepository.findById(taskId).get();// 我这里是要根据任务名称查询旗下所有的最底级菜单名List<String> themeNames = themeTemplate.getAllThemeNames(exportTaskPO);List<String> excludeList = Arrays.asList("快照", "all");// 根据菜单列表去获取每个菜单的列名数据List<Map<String, Object>> fieldNames = themeFieldRepository.findFieldName(themeNames);fieldNames.removeIf(map -> excludeList.contains(String.valueOf(map.get("fieldName"))));// Excel文件标题List<String> rowHead = Arrays.asList("表名", "字段名", "字段类型");// 文件名String filename = exportTaskPO.getTaskName() + "_数据字典.xlsx";try {// 获取输出流对象ExcelWriter writer = ExcelUtil.getWriter();// 写入标题writer.writeHeadRow(rowHead);// 获取导出的数据List<List<Object>> rows = loadRowList(fieldNames, writer);// 一次性写出内容,使用默认样式,强制输出标题writer.write(rows,true);// response为HttpServletResponse对象response.setContentType("application/vnd.ms-excel;charset=utf-8");// test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码response.setHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(filename,"UTF8"));ServletOutputStream out = response.getOutputStream();writer.flush(out, true);// 此处记得关闭输出Servlet流IoUtil.close(out);} catch (IOException e) {e.printStackTrace();}
}private List<List<Object>> loadRowList(List<Map<String, Object>> fieldNames, ExcelWriter writer){// 定义起始行int index = 1;List<List<Object>> rows = new LinkedList<>();// 按照表名进行分组LinkedHashMap<Object, List<Map<String, Object>>> themeFieldName  = fieldNames.stream().collect(Collectors.groupingBy(map -> map.get("themeName"), LinkedHashMap::new, Collectors.toList()));for(Map.Entry<Object,List<Map<String, Object>>> listEntry : themeFieldName.entrySet()){List<Map<String, Object>> mapList = listEntry.getValue();// 根据数据条数设置合并单元格信息if(mapList.size() == 1){index = index + mapList.size();}else {// 难点就是下面的合并单元格的规则编写  参数含义: //<int firstRow,int lastRow,int firstColumn,int lastColumn,Object content,boolean isSetHeaderStyle>writer.merge(index,index+mapList.size()-1,0,0,null,true);index = index + mapList.size();}// 保存数据mapList.forEach(stringObjectMap -> {List<Object> rowA = null;rowA = CollUtil.newArrayList(stringObjectMap.get("themeName"),stringObjectMap.get("fieldName"),fieldTypeToString((String) stringObjectMap.get("fieldType")));rows.add(rowA);});}return rows;}

最终下载的文件格式为:
在这里插入图片描述

2、打包为zip返回

这种一般时间比较长,建议先将所有的文件打包整理好存放在磁盘某个地方,给前端返回的是文件的工程路径,前端使用windows.open再去请求一次即可。

实例:

1、这种一般打包的话,可以打包本地的某个文件夹下的所有文件:

直接使用ZipUtil工具就可以搞定:

 // 调用打包压缩包,将/sql/目录下的某个文件夹压缩为“.zip”的格式,  最后一个参数true的意思是withSrcDirZipUtil.zip("/sql/" + exportTaskPO.getTaskName() +"-"+ DateUtil.format(DateUtil.date(),"yyyyMMdd"),"/sql/"+exportTaskPO.getTaskName() +"-"+ DateUtil.format(DateUtil.date(),"yyyyMMdd") + ".zip",true);

2、还有一种情况就是文件压根不在本地,在文件服务器上,这种一般有两种解决,可以先在文件服务器把文件下载回来放到本地再调用上面的办法。还有一种思路就是直接压缩流:

public void downloadFile(Map<String, String> map, HttpServletRequest request, HttpServletResponse response){String fileName = "test.zip";try {File zipFile = File.createTempFile("test", ".zip");FileOutputStream f = new FileOutputStream(zipFile);/*** 作用是为任何OutputStream产生校验和* 第一个参数是制定产生校验和的输出流,第二个参数是指定Checksum的类型 (Adler32(较快)和CRC32两种)*/CheckedOutputStream csum = new CheckedOutputStream(f, new Adler32());// 用于将数据压缩成Zip文件格式ZipOutputStream zos = new ZipOutputStream(csum);for (String id: map.keySet()) {InputStream inputStream = commonOssDao.getInputStream(id);// 对于每一个要被存放在压缩包的文件,都必须调用ZipOutputStream对象的putNextEntry()方法,确保压缩包里面的文件不重名zos.putNextEntry(new ZipEntry(map.get(id)));int byteRead = 0;// 向压缩文件中输出数据while((byteRead = inputStream.read()) != -1){zos.write(byteRead);}inputStream.close();zos.closeEntry(); // 当前文件写完,定位为下一条项目}zos.close();String header = request.getHeader("User-Agent").toUpperCase();if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) {fileName = URLEncoder.encode(fileName, "utf-8");fileName = fileName.replace("+", "%20");    //IE下载文件名空格变+号问题} else {fileName = new String(fileName.getBytes(), "UTF8");}response.reset();response.setContentType("application/zip");response.setContentType("application/octet-stream; charset=utf-8");response.setHeader("Location", fileName);response.setHeader("Cache-Control", "max-age=0");response.setHeader("Content-Disposition", "attachment; filename=" + fileName);FileInputStream fis = new FileInputStream(zipFile);BufferedInputStream buff = new BufferedInputStream(fis);BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());byte[] car = new byte[1024];int l = 0;while (l < zipFile.length()){int j = buff.read(car,0,1024);l += j;out.write(car,0,j);}// 关闭流out.close();buff.close();fis.close();//  zipFile.delete();} catch (IOException e) {log.warn("数据包下载出现异常");log.warn(e.toString());e.printStackTrace();}
}

http://chatgpt.dhexx.cn/article/nAdJF8E3.shtml

相关文章

java导出excel的两种方式

博主简介&#xff1a;原互联网大厂tencent员工&#xff0c;网安巨头Venustech员工&#xff0c;阿里云开发社区专家博主&#xff0c;微信公众号java基础笔记优质创作者&#xff0c;csdn优质创作博主&#xff0c;创业者&#xff0c;知识共享者,欢迎关注&#xff0c;点赞&#xff…

数据的导出方法

实现页面数据的导出 怎样实现网页数据的导出到本地&#xff0c;这里实现的是以Excel表格的格式导入到本地. 比如这样的个表格我怎样实现把数据导出放到一个到Excel表格中保存到本地&#xff0c; 从下面划红线部分可以看出这里的数据是通过三个下拉框的查询条件得到的数据&…

Pr 入门系列之十四:导出

视频工作流程中的最后一步就是导出。 Pr 中&#xff0c;可以方便地导出序列或剪辑&#xff0c;发送给他人&#xff0c;分享到社交媒体渠道&#xff0c;或者创建 DCP&#xff08;数字电影包&#xff09;文件用于影院分发。 ◆ ◆ ◆ 导出的一般流程 1、首先&#xff0c;在时间…

正态分布

正态分布 我们来对某一个年级做一项调查&#xff0c;看一看这个年级到底有多巨。于是&#xff0c;他们统计了每个同学一周刷题的时间。得到的结果如下&#xff1a; 可以看出&#xff0c;大多数人每周都有7-8个小时做题&#xff0c;有少部分蒟蒻(比如我)每周只有1-3个小时做题&…

广义pareto分布_帕累托分布广义帕累托分布

PDF、PMF、CDF 1. 概念解释 PDF:概率密度函数(probability density function), 在数学中,连续型随机变量的概率密度函数(在不至于混淆时可以简称为密度函数)是一个描述这个随机变量的输出值,在某个确定的取值点附近的可能性的函数。 PMF:概率质量函数(probability mass fun…

离散均匀分布

离散均匀分布 n 个值中的每一个具有相等的概率 1/ n 截图来源&#xff1a;Discrete Uniform Distribution 例子&#xff1a; 投掷一个骰子6个值中每个值出现的概率为 1 / 6 1/6 1/6 投掷两个骰子出现的两值之和&#xff0c;结果分布不再均匀&#xff0c;因为并非所有和的概率都…

平均分布

转载请注明出处&#xff1a;http://blog.csdn.net/liu_sn/article/details/79333368 今天遇到本很好玩的书&#xff0c;《世界是随机的:大数据时代的概率统计学》&#xff0c;在讲分布的时候作者说&#xff1a;概率分布就是概率论中的小九九。很有意思&#xff0c;看了之后确实…

边缘分布

什么是边缘分布函数&#xff0c;有那些性质 设 F ( x , y ) F(x,y) F(x,y)为随机变量 ( X , Y ) (X,Y) (X,Y)的分布函数&#xff0c;则 F ( x , y ) P { X ≤ x , Y ≤ y } F(x,y)P\{X \le x,Y \le y\} F(x,y)P{X≤x,Y≤y} 令 y → ∞ y \rightarrow \infty y→∞&#xff…

度分布的概念及形状

一、度分布的概念 把网络中节点的度按从小到大排序&#xff0c;从而统计得到度为k的节点占整个网络节点数的比例怕p k _k k​。例如下图&#xff1a; 从概率统计的角度看&#xff0c;p k _k k​也可以视为网络中一个随机选择的节点的度为k的概率&#xff0c;这就是度分布的概…

正确理解泊松分布

很多人在上概率论这门课的时候就没搞明白过泊松分布到底是怎么回事&#xff0c;至少我就是如此。虽然那个时候大家都会背“当试验的次数趋于无穷大&#xff0c;而乘积np固定时&#xff0c;二项分布收敛于泊松分布”&#xff0c;大部分的教科书上也都会给出这个收敛过程的数学推…

白话解释正态分布

复习一个统计学方面的课题&#xff0c;想找些资料看看&#xff0c;结果发现&#xff0c;就算是最基本的一些统计学概念&#xff0c;能找到的中文资料&#xff0c;读起来都是这么的佶屈聱牙&#xff0c;似乎都是从教科书里拷贝几个名词解释给放到一起&#xff0c;就算是一篇文章…

常用分布函数

0-1分布 设随机变量X只可能取0与1两个值&#xff0c;分布律为 则称X服从以p为参数的0-1分布 即 X 0 1 P 1-p p 用于描述: 对新生儿性别进行登记&#xff1b;检查产品质量是否合格&#xff1b;某车间的电力消耗是否超负荷 二项分布 设随机变量X只可能取0和1两个值&…

[R语言]正态分布

目录 分布 连续型变量的分布 正态分布 正态分布的推导 正态分布密度曲线 dnorm 正态分布的概率计算 正态分布累积曲线 总体分位数和尾概率 正态分布案例之一 R语言正态分布函数 正态分布相应的概率计算 正态分布的检验 shapiro.test()函数 Kolmogorov-Smirnov连续…

概率分布汇总

概率分布、总体分布、抽样分布&#xff0c;一开始很容易搞混&#xff0c;还以为是同一个理论&#xff0c;不同的概念&#xff0c;毕竟都是分布&#xff0c;又都是统计学里面的概率。今天就来理解理解这个东西吧。 概率分布是指随机变量的各取值与该取值对应的概率之间呈现的规…

拉普拉斯分布

如果随机变量的概率密度函数分布如下图所示&#xff0c;那么它就是拉普拉斯分布&#xff0c;记为x-Laplace&#xff08;μ,λ)&#xff0c;其中&#xff0c;μ 是位置参数&#xff0c;λ 是尺度参数。如果 μ 0&#xff0c;那么&#xff0c;正半部分恰好是尺度为 1/λ(或者λ&…

高斯分布

正态分布&#xff08;Normal distribution&#xff09;又名高斯分布&#xff08;Gaussian distribution&#xff09;&#xff0c;是一个在数学、物理及工程等领域都非常重要的概率分布&#xff0c;在统计学的许多方面有着重大的影响力。 若随机变量X服从一个数学期望为μ、标准…

机器学习小组知识点23:F分布(F Distribution)-R语言代码

F分布的用途&#xff1a;用于方差分析、协方差分析和回归分析等。 定义 一个 F -分布的随机变量是两个卡方分布变量的比率: U1/d1U2/d2=U1/U2d1/d2 其中&#xff1a; U1和U2呈卡方分布&#xff0c;它们的自由度&#xff08;degree of freedom&#xff09;分别是d1和d2。 …

F分布及其应用

F分布是1924年英国统计学家R.A.Fisher提出,并以其姓氏的第一个字母命名的。它是一种非对称分布,有两个自由度,且位置不可互换。设X服从自由度为n1的卡方分布, Y服从自由度为n2的卡方分布,且X,Y独立,则称随机变量F=(X⁄n1 )/(Y⁄n2 )服从自由度为(n1,n2)的F分布,记为F~F…

TeamTalk各个服务的IP配置方案

本人微信公众号&#xff1a;CPP进阶之旅 如果觉得这篇文章对您有帮助&#xff0c;欢迎关注 “CPP进阶之旅” 学习更多技术干货 TeamTalk各个服务的IP配置方案 1.纯公司内网2.公网ip3.公网ip&#xff0c;路由器映射相关文章重要说明 TeamTalk源码中的IM_SERVER下共有8种服务器&a…

TeamTalk部署详细教程(最全最新TeamTalk部署教程助你一次部署成功)

本人微信公众号&#xff1a;CPP进阶之旅 如果觉得这篇文章对您有帮助&#xff0c;欢迎关注 “CPP进阶之旅” 学习更多技术干货 TeamTalk部署详细教程 背景1、更新操作系统2、删除已经安装的软件3、安装必要的依赖软件4、安装mysql4.1 下载4.2 解压编译4.3 添加mysql用户4.4 修改…