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类型,然后把里面的“\”替换成“/”就行了。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。