java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > JAVA后台实现文件批量下载

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

作者: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类型,然后把里面的“\”替换成“/”就行了。

总结

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

您可能感兴趣的文章:
阅读全文