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

文件下载的几种办法:

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 >= 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();
            // 设置文件对应后缀的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<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);
            // 文件流上面加一层缓冲流,目的为了加快速度,减少IO
            BufferedInputStream 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的意思是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<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();
        }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在现代办公环境中,数据整理和处理是日常工作中不可或缺的一部分。随着数据量的不断增长,手动处理变得既费时又容易出错。Python作为一种功能强大的编程语言,提供了自动化处理数据的能力,极大地提高了工作效率。下面将介绍一个Python自动化办公的源码,它能够批量找出包含特定内容的数据,并将这些数据整理成一个新的Excel表格。该源码的核心功能是通过Python的pandas库来实现的。Pandas是一个强大的数据分析工具,它能够轻松读取各种格式的数据集,如CSV、Excel等,并提供了一系列数据处理的功能。用户只需提供原始数据的路径、需要查找的关键词以及输出文件的名称,该脚本就能够自动完成以下操作:读取原始数据:通过pandas的read_excel或read_csv函数,读取用户提供的原始数据文件。数据筛选:根据用户提供的关键词,使用pandas的条件筛选功能,找出包含特定内容的数据行。数据整理:对筛选出的数据进行整理,如删除不必要的列、格式化日期等,以便生成清晰可读的报告。生成新表格:将整理后的数据导出为新的Excel文件,用户可以自定义文件名和保存路径。压缩打包:为了方便传输和存档,脚本还将提供一个选项,将生成的Excel文件打包成.zip格式的压缩文件。这个Python自动化办公源码非常适合那些需要处理大量数据并快速生成报告的办公场景。例如,财务人员可以使用它来筛选出特定时间段内的财务记录,市场分析师可以用它来提取特定产品的销售数据。通过这种方式,原本耗时数小时甚至数天的工作,现在只需几分钟即可完成,大大提升了工作效率和准确性。总之,这个Python自动化办公源码是一个强大而实用的工具,它能够帮助用户从繁琐的数据筛选和整理工作中解放出来,专注于更加有价值的分析和决策工作。无论是对于数据科学新手还是经验丰富的专业人士,这个源码都是一个值得尝试的解决方案。重新回答||
大奇excel转kml专家适合任何EXCEL,可以集成点、线、多段线、图片、3D模式,可以灵活设置适应任何EXCEL表格,可以用于任何基站、管道、线路、通信设计、天然气管道、道路选线、高中低压电力线路及水管网线路的设计! 这是32位专版,注意:excel转kml专家9.6(win8_32位)版本发布了,非常强大,性能卓越,地理数据处理的利器,专业成就未来!快来测试吧!1.必须运行在64位的系统 2.必须安装64位的office2013 3.必须以管理员权限运行 4.必须安装32位的AccessDatabaseEngine_X64.exe 修复众多bug不说,完美生成带图片资源的kmz文件,再也不会找不到图片和3D杆塔路径了。同时支持RTK测量的表格转kml和kmz,支持csv文件格式,生成效果自由灵活,适应几乎所有的表格格式,自带几十种模板,适应通信设计、电力设计、测量测绘、地质勘探、公路、铁路、管线设计、商业选址、物流管理、智能交通、安全监控等几乎所有需要GPS定位信息的行业, 是科学研究、外出旅行、工程施工、项目规划等必备的强大软件! 大奇excel转kml专家 v9.9更新日志 一、支持三相线路杆塔一体成型,支持模型转角,支持点、线、线段、多边形、图片、3D、文字、表格一步导入,支持ini配制文件和批量导入,适应任意表格,导入几万条数据分秒钟的事情! 二、 在转换带有图片资源及3D模型的表格文件时,若生成的是KML文件文件拷到其它电脑后,往往会找不到图片和3D模型资源,图片显示一个X或者模型无显示。这时,可以生成KMZ文件,KMZ文件在生成时,已经把对应的图片资源及3D模型保存在整个KMZ文件内,因此,可以拷贝到任何路径和电脑查看,不会出现错误。 三、 支持小数度及度分秒、及RTK测量仪导出的数据。RTK测量仪导出的数据格式因不同的仪器不同,有的省略了度分秒的符号,把度分秒写成小数度的格式,如19.18181818,其实是19度18分18.1818秒。还有一种用:来代替度分秒的符号,例如:19:18:18.1818N,表示的是19度18分18.1818秒。程序都可以支持读取转换。 四、 增加了对CSV文件的读取转换,可以实现批量转换CSV文件了 五、带有几十种常见的转换模板,从通信设计、基站定位、电力杆塔、管道线路、交通线路、政府决策等使用的多种模板格式,几乎支持任意excel模板。 六、带有详细的说明书,方便使用时查看 大奇excel转kml专家截图
一彩快递单打印软件是一款专业的快递单打印软件,软件改变快递员用手写快递单的历史,大大增加了员工之间的工作效率,也节省了企业的成本。软件操作方便、功能完善功能强大、个性化极强,让快递单打印变得快速简单。软件界面美观简洁、简单全面、实用方便,无需培训,即可快速上手,轻轻松松完成日常快递单打印功能,真正做到简单全面实用。是用户实现快递单打印功能的好帮手。 一彩快递单打印软件功能 1、系统支持近百种国内国际快递单,主要包括: EMS、UPS、DHL、Fedex、TNT、CCES快递、顺丰速运、申通快递、圆通速递、龙邦物流、优速快递、联昊通快递、加运美速递、全日通快递、港中能达、世纪同城、越丰物流、快捷快递、新邦快递、速尔快递、YCC快递、汇通快递、源安达快运、运通中港、韵达快运、信封等快递单; 2、软件简单易用、通俗易懂,只需几分钟就可以快速上手。 3、强大的自定义格式功能;在系统中没有您所需要的快递单,可自行添加新的快递单模板并设计。   4、支持一键自动识别淘宝等地址格式的高级功能; 5、可存储10万个以上收、发件人资料,随时方便调用; 6、支持默认发件人,尽量减少选择和录入。 7、绿色软件,无需插件,运行效率高,无需联网便可使用,重装系统不影响使用; 8、打印精确美观,字体、字体大小、字体位置可随意调整; 9、支持所有品牌和型号的针式打印机; 10、强大导入导出功能,可直接从Excel文件中导入导出; 11、支持自动数据备份及恢复; 12、 强大的用户权限设置,轻松设置操作员的操作权限; 13、 智能在线升级服务,正版用户免费升级软件最新版本。 一彩快递单打印软件 v1.24更新日志 增加批量打印自动保存功能; 更新民邦快递单号查询追踪功能; 更新城市之星快递单; 更新信丰物流快递单; 更新民邦快递快递单; 更新申通快递快递单; 一彩快递单打印软件截图

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值