JAVA后台实现文件批量下载方式

 更新时间:2024年05月30日 09:46:03   作者:utada hikki  
这篇文章主要介绍了JAVA后台实现文件批量下载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

JAVA后台实现文件批量下载

工具类

	/**
     * 本地文件路径
     */
	private static final String FILE_PATH = "F:\\test";
/**
     * 批量下载文件
     *
     * @param list     批量文件集合(前端只传id集合,后端去查数据库拿到文件信息)
     * @param request  request
     * @param response response
     * @param <T>      实体类 extends BaseEntityPoJo 
     */
    public static <T extends BaseEntityPoJo> void batchDownloadFile(List<T> list, HttpServletRequest request, HttpServletResponse response) {
        //设置响应头信息
        response.reset();
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        //设置压缩包的名字,date为时间戳
        String date = DateUtil.formatDateTimeSecond(new Date());
        String downloadName = "压缩包" + date + ".zip";
        //返回客户端浏览器的版本号、类型
        String agent = request.getHeader("USER-AGENT");
        try {
            //针对IE或者以IE为内核的浏览器:
            if (agent.contains("MSIE") || agent.contains("Trident")) {
                downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
            } else {
                //非IE浏览器的处理:
                downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");

        //设置压缩流:直接写入response,实现边压缩边下载
        ZipOutputStream zipOs = null;
        //循环将文件写入压缩流
        DataOutputStream os = null;
        //文件
        File file;
        try {
            zipOs = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            //设置压缩方法
            zipOs.setMethod(ZipOutputStream.DEFLATED);
            //遍历文件信息(主要获取文件名/文件路径等)
            for (T t : list) {
                try {
                    //文件名(包含后缀名,如:测试.pdf)
                    Field field = t.getClass().getDeclaredField("name");
                    field.setAccessible(true);
                    String name = field.get(t).toString();
                    //本地文件路径(绝对路径,包含后缀名,如:F:\\test\\测试.pdf),这里是在windows上测试的,路径是反斜杠
                    String path = FILE_PATH + File.separator + name;
                    log.info("batchDownloadFile:[filePath:{}]", path);
                    file = new File(path);
                    if (!file.exists()) {
                        throw new RuntimeException("文件不存在");
                    }
                    //添加ZipEntry,并将ZipEntry写入文件流
                    zipOs.putNextEntry(new ZipEntry(name));
                    os = new DataOutputStream(zipOs);
                    FileInputStream fs = new FileInputStream(file);
                    byte[] b = new byte[100];
                    int length;
                    //读入需要下载的文件的内容,打包到zip文件
                    while ((length = fs.read(b)) != -1) {
                        os.write(b, 0, length);
                    }
                    //关闭流
                    fs.close();
                    zipOs.closeEntry();
					//==============此处如果是网络文件路径,可按如下方式读取=============
					/*
					//文件名(包含后缀名,如:测试.pdf)
                    Field field = t.getClass().getDeclaredField("name");
                    field.setAccessible(true);
                    String name = field.get(t).toString() + ".pdf";
                    //网络文件路径(浏览器可直接访问的路径,如:http://192.168.0.12/frame-service-gengbao/document/四川省2022第四季度报告.pdf)
                    Field urlField = t.getClass().getDeclaredField("url");
                    urlField.setAccessible(true);
                    URL url = new URL(urlField.get(t).toString());
                    URLConnection connection = url.openConnection();
                    InputStream is = connection.getInputStream();
                    //添加ZipEntry,并将ZipEntry写入文件流
                    zipOs.putNextEntry(new ZipEntry(name));
                    os = new DataOutputStream(zipOs);
                    byte[] b = new byte[100];
                    int length;
                    //读入需要下载的文件的内容,打包到zip文件
                    while ((length = is.read(b)) != -1) {
                        os.write(b, 0, length);
                    }
                    is.close();
                    zipOs.closeEntry();
                    */
                } catch (IllegalAccessException | NoSuchFieldException e) {
                    log.error("下载文件出错![{}]", e.getMessage());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
                if (zipOs != null) {
                    zipOs.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

控制层

	/**
     * 批量下载(测试时可改为GET请求,浏览器直接调用接口)
     *
     * @param ids      用于查询相关表获取文件信息
     * @param request  request
     * @param response response
     */
    @GetMapping("/batchDownloadFile")
    @ApiOperation("批量下载")
    public void batchDownloadFile(@RequestParam("ids") final String ids,
                                  HttpServletRequest request,
                                  HttpServletResponse response) {
        log.info("downloadPlanFile:批量下载[ids:{},request:{},response:{}]", ids, request, response);
        List<Integer> idList = ControllerHelper.splitToLong(ids);
        List<RegulatoryReport> list = service.list(idList);
        FileUtil.batchDownloadFile(list, request, response);
    }

上面用到的方法

分割字符串

public static List<Integer> splitToLong(final String str) {
        return StringUtils.isEmpty(str) ? Collections.emptyList() : Stream.of(str.split(",")).map(Integer::valueOf).collect(Collectors.toList());
    }

获取时间戳

	/**
     * 将日期解析成yyyyMMddHHmmss的字符串
     *
     * @param date the date
     * @return the string
     */
    public static String formatDateTimeSecond(Date date) {
        if (date == null) {
            return "";
        }
        return new SimpleDateFormat(DATETIME_STAMP_SECOND, Locale.CHINA).format(date);
    }

注意:

我这里为了对各种文件通用下载,工具类用的泛型方法,如果不需要泛型的,直接传入自己需要的实体类集合就可以了。

测试接口

其他记录

在Java中,当变量的数据类型为File时,值的斜杠都是“\”(new File(filePath), 就会变成xx\xx\1.txt);

当变量的数据类型为String 时,斜杠都是“/”(String filePath = “xx/xx/1.txt”);

File f = new File(filePath);
String path = (f+“”).replaceAll(“\\”, “/”);

把f转成String类型,然后把里面的“\”替换成“/”就行了。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java 单例模式的实现资料整理

    Java 单例模式的实现资料整理

    这篇文章主要介绍了Java 单例模式的实现的相关资料,并附简单实例代码,需要的朋友可以参考下
    2016-10-10
  • JAVA 十六进制与字符串的转换

    JAVA 十六进制与字符串的转换

    笔者前几日在开服过程中需要将字符串转化成为16进制的字符串,在网上找到了一些方法尝试之后,均发现存在一个问题-->字符串转为16进制后再转回来,英文正常,中文出现乱码
    2009-05-05
  • 详解Java中的Lambda表达式

    详解Java中的Lambda表达式

    Lambda表达式是Java SE 8中一个重要的新特性。这篇文章主要介绍了Java中的Lambda表达式 ,需要的朋友可以参考下
    2019-04-04
  • OGNL表达式基本语法与用法详解

    OGNL表达式基本语法与用法详解

    这篇文章主要介绍了OGNL表达式基本语法与用法详解,具有一定参考价值。需要的朋友可以了解下。
    2017-09-09
  • springcloud gateway实现简易版灰度路由步骤详解

    springcloud gateway实现简易版灰度路由步骤详解

    这篇文章主要为大家介绍了springcloud gateway实现简易版灰度路由步骤详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • spring cloud config分布式配置中心的高可用问题

    spring cloud config分布式配置中心的高可用问题

    本文给大家介绍spring cloud config分布式配置中心的高可用问题,通过整合Eureka来实现配置中心的高可用,需要的朋友参考下本文
    2018-01-01
  • Java并发程序刺客之假共享的原理及复现

    Java并发程序刺客之假共享的原理及复现

    前段时间在各种社交平台“雪糕刺客”这个词比较火,而在并发程序中也有一个刺客,那就是假共享。本文将通过示例详细讲解假共享的原理及复现,需要的可以参考一下
    2022-08-08
  • Java实现双保险线程的示例代码

    Java实现双保险线程的示例代码

    这篇文章主要介绍了Java实现双保险线程的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • Spring多线程的使用以及问题详解

    Spring多线程的使用以及问题详解

    在我们开发系统过程中,经常会处理一些费时间的任务(如:向数据库中插入大量数据),这个时候就就需要使用多线程,下面这篇文章主要给大家介绍了关于Spring多线程的使用以及问题的相关资料,需要的朋友可以参考下
    2022-05-05
  • java中VO PO DTO POJO BO DO对象的应用场景及使用方式

    java中VO PO DTO POJO BO DO对象的应用场景及使用

    文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它们在不同场景下的应用
    2025-01-01

最新评论