办公设备维修网
资讯中心 您所在的位置:网站首页 资讯中心 文件导出与下载(Excel,Zip)等几种方式

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

2024-06-26 21:04:56| 来源: 网络整理

文件下载的几种办法: 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; @Synchronized public static BigExcelWriter createBigExcelWriter(String fileName , int columnSize){ BigExcelWriter bigWriter = cn.hutool.poi.excel.ExcelUtil.getBigWriter(PATH + fileName + SUFFIX); for (int size = columnSize; size >=;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 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(); // 设置文件对应后缀的ContentType response.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 head = new HashMap(); // 开始准备写入数据 for(PackageDataItemPO packageDataItemPO:packageDataItemPOList){ // 将查询的数据转换为map Map map = getHasSortMap(packageDataItemPO); bigExcelWriter.writeRow(map,count.getAndIncrement() == 0); } bigExcelWriter.close(); // 上面的过程就是文件的写入过程并且保存在了/excel/目录下 // 下面就是把这个文件读取出来,以流的形式返回 File excelFile= new File("/excel/"+fileName1); FileInputStream fis = new FileInputStream(excelFile); // 文件流上面加一层缓冲流,目的为了加快速度,减少IO BufferedInputStream buff = new BufferedInputStream(fis); // 同理,输出流上也套了一层缓冲的输出流 BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); byte[] car = new byte[1024]; int l = 0; // 按字节读取文件 while (l e.printStackTrace(); }} private Map getHasSortMap(PackageDataItemPO packageDataItemPO){ Map 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 themeNames = themeTemplate.getAllThemeNames(exportTaskPO); List excludeList = Arrays.asList("快照", "all"); // 根据菜单列表去获取每个菜单的列名数据 List fieldNames = themeFieldRepository.findFieldName(themeNames); fieldNames.removeIf(map -> excludeList.contains(String.valueOf(map.get("fieldName")))); // Excel文件标题 List rowHead = Arrays.asList("表名", "字段名", "字段类型"); // 文件名 String filename = exportTaskPO.getTaskName() + "_数据字典.xlsx"; try { // 获取输出流对象 ExcelWriter writer = ExcelUtil.getWriter(); // 写入标题 writer.writeHeadRow(rowHead); // 获取导出的数据 List 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 loadRowList(List fieldNames, ExcelWriter writer){ // 定义起始行 int index = 1; List rows = new LinkedList(); // 按照表名进行分组 LinkedHashMap themeFieldName = fieldNames.stream().collect(Collectors.groupingBy(map -> map.get("themeName"), LinkedHashMap::new, Collectors.toList())); for(Map.Entry listEntry : themeFieldName.entrySet()){ List mapList = listEntry.getValue(); // 根据数据条数设置合并单元格信息 if(mapList.size() == 1){ index = index + mapList.size(); }else { // 难点就是下面的合并单元格的规则编写 参数含义: // writer.merge(index,index+mapList.size()-1,0,0,null,true); index = index + mapList.size(); } // 保存数据 mapList.forEach(stringObjectMap -> { List 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的意思是withSrcDir ZipUtil.zip("/sql/" + exportTaskPO.getTaskName() +"-"+ DateUtil.format(DateUtil.date(),"yyyyMMdd"),"/sql/"+exportTaskPO.getTaskName() +"-"+ DateUtil.format(DateUtil.date(),"yyyyMMdd") + ".zip",true);

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

public void downloadFile(Map 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 log.warn("数据包下载出现异常"); log.warn(e.toString()); e.printStackTrace(); }}


【本文地址】 转载请注明 

最新文章

推荐文章

CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备16040606号-1