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 countDownLatch如何实现多线程任务阻塞等待

    Java countDownLatch如何实现多线程任务阻塞等待

    这篇文章主要介绍了Java countDownLatch如何实现多线程任务阻塞等待,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java实现连连看算法

    Java实现连连看算法

    这篇文章主要为大家详细介绍了Java实现连连看算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-06-06
  • cmd编译运行java程序的方法

    cmd编译运行java程序的方法

    本文主要介绍了cmd编译运行java程序的方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 浅谈log4j 不打印异常堆栈

    浅谈log4j 不打印异常堆栈

    这篇文章主要介绍了浅谈log4j 不打印异常堆栈,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • Java线程编程中isAlive()和join()的使用详解

    Java线程编程中isAlive()和join()的使用详解

    这篇文章主要介绍了Java线程编程中isAlive()和join()的使用详解,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • Java中JDBC连接池的基本原理及实现方式

    Java中JDBC连接池的基本原理及实现方式

    本文详细讲解了Java中JDBC连接池的基本原理及实现方式,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • 使用Spring自定义注解实现任务路由的方法

    使用Spring自定义注解实现任务路由的方法

    本篇文章主要介绍了使用Spring自定义注解实现任务路由的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • MybatisPlus如何调用count函数

    MybatisPlus如何调用count函数

    这篇文章主要介绍了MybatisPlus如何调用count函数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • 一文读懂Jvm类加载机制

    一文读懂Jvm类加载机制

    这篇文章主要介绍了一文读懂Jvm类加载机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • 深入了解Java排序算法

    深入了解Java排序算法

    本文主要介绍了深入了解Java排序算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2007-03-03

最新评论