目录

  • 1、前置条件
  • 2、单一文件下载
    • 2.1、本地文件下载
    • 2.2、网络文件下载
  • 3、zip压缩包批量下载
    • 3.1、本地文件批量下载
    • 3.2、网络文件批量下载
  • 4、说三遍

1、前置条件

demo中,将多个文件通过zip的形式进行下载,所以需要引入以下maven坐标:

        <dependency><groupId>org.apache.commons</groupId><artifactId>commons-compress</artifactId><version>1.20</version></dependency>

为了更好的代码可读性,将针对本地、网络文件下载、zip压缩包批量下载封装一个工具类,代码如下:
下载实现的核心就是下面的工具类代码,可以在任意的项目中进行使用;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;/*** @Author: LiHuaZhi* @Date: 2022/1/19 13:54* @Description:**/
public class FileUtil {private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);private static MimetypesFileTypeMap mimetypesFileTypeMap;/*** 下载http文件流** @param urlStr* @param request* @param response* @param fileName* @return*/public static void downloadHttpFile(String urlStr, HttpServletRequest request, HttpServletResponse response, String fileName) {ServletOutputStream out = null;InputStream inputStream = null;try {URL url = new URL(urlStr);HttpURLConnection conn = (HttpURLConnection) url.openConnection();//得到输入流inputStream = conn.getInputStream();//获取自己数组byte[] getData = FileUtil.inputStreamToByte(inputStream);// 下载out = response.getOutputStream();long contentLength = getData.length;FileUtil.setResponse(fileName, contentLength, request, response);out.write(getData);out.flush();} catch (Exception e) {throw new RuntimeException("下载失败!");} finally {try {if (out != null) {out.close();}if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}}//File、FileInputStream 转换为byte数组public static byte[] inputStreamToByte(InputStream inputStream) {try {byte[] buffer = new byte[1024];int len = 0;ByteArrayOutputStream bos = new ByteArrayOutputStream();while ((len = inputStream.read(buffer)) != -1) {bos.write(buffer, 0, len);}bos.close();return bos.toByteArray();} catch (Exception e) {throw new RuntimeException("文件转换失败!");}}/*** 下载文件流** @param file* @param request* @param response* @param fileName* @return*/public static void downloadFile(File file, HttpServletRequest request, HttpServletResponse response, String fileName) {if (file != null && file.exists() && file.length() > 0L) {try {RandomAccessFile randomFile = new RandomAccessFile(file, "r");Throwable var5 = null;Object var54;try {ServletOutputStream out = response.getOutputStream();Throwable var7 = null;try {long contentLength = randomFile.length();String range = request.getHeader("Range");long start = 0L;long end = 0L;if (range != null && range.startsWith("bytes=")) {String[] values = range.split("=")[1].split("-");start = Long.parseLong(values[0]);if (values.length > 1) {end = Long.parseLong(values[1]);}}int requestSize;if (end != 0L && end > start) {requestSize = Long.valueOf(end - start + 1L).intValue();} else {requestSize = 2147483647;}FileUtil.setResponse(fileName, contentLength, request, response);randomFile.seek(start);byte[] buffer;for (int needSize = requestSize; needSize > 0; needSize -= buffer.length) {buffer = new byte[1024];int len = randomFile.read(buffer);if (needSize < buffer.length) {out.write(buffer, 0, needSize);} else {out.write(buffer, 0, len);if (len < buffer.length) {break;}}}out.flush();var54 = null;} catch (Throwable var47) {var7 = var47;throw var47;} finally {if (out != null) {if (var7 != null) {try {out.close();} catch (Throwable var46) {var7.addSuppressed(var46);}} else {out.close();}}}} catch (Throwable var49) {var5 = var49;throw var49;} finally {if (randomFile != null) {if (var5 != null) {try {randomFile.close();} catch (Throwable var45) {var5.addSuppressed(var45);}} else {randomFile.close();}}}} catch (IOException var51) {logger.debug(var51.getMessage(), var51);throw new RuntimeException(var51.getMessage());}} else {throw new RuntimeException("文件为空或不存在!");}}/*** @param fileName* @param contentLength* @param request* @param response* @return*/public static void setResponse(String fileName, long contentLength, HttpServletRequest request, HttpServletResponse response) {try {response.setContentType(FileUtil.getContentType("0.jpg"));boolean isPreview = "preview".equalsIgnoreCase(request.getParameter("source"));response.addHeader("Content-Disposition", (!isPreview ? "attachment; " : "") + "filename*=utf-8'zh_cn'" + URLEncoder.encode(fileName, "UTF-8"));response.setHeader("Accept-Ranges", "bytes");String range = request.getHeader("Range");if (range == null) {response.setHeader("Content-Length", String.valueOf(contentLength));} else {response.setStatus(206);long requestStart = 0L;long requestEnd = 0L;String[] ranges = range.split("=");if (ranges.length > 1) {String[] rangeDatas = ranges[1].split("-");requestStart = Long.parseLong(rangeDatas[0]);if (rangeDatas.length > 1) {requestEnd = Long.parseLong(rangeDatas[1]);}}long length = 0L;if (requestEnd > 0L) {length = requestEnd - requestStart + 1L;response.setHeader("Content-Length", String.valueOf(length));response.setHeader("Content-Range", "bytes " + requestStart + "-" + requestEnd + "/" + contentLength);} else {length = contentLength - requestStart;response.setHeader("Content-Length", String.valueOf(length));response.setHeader("Content-Range", "bytes " + requestStart + "-" + (contentLength - 1L) + "/" + contentLength);}}} catch (Exception e) {throw new RuntimeException("response响应失败!");}}public static String getContentType(String fileName) {if (mimetypesFileTypeMap == null) {mimetypesFileTypeMap = new MimetypesFileTypeMap();}return mimetypesFileTypeMap.getContentType(fileName);}/*** 将磁盘的多个文件打包成压缩包并输出流下载** @param pathList* @param request* @param response*/public static void zipDirFileToFile(List<Map<String, String>> pathList, HttpServletRequest request, HttpServletResponse response) {try {// 设置response参数并且获取ServletOutputStreamZipArchiveOutputStream zous = getServletOutputStream(response);for (Map<String, String> map : pathList) {String fileName = map.get("name");File file = new File(map.get("path"));InputStream inputStream = new FileInputStream(file);setByteArrayOutputStream(fileName, inputStream, zous);}zous.close();} catch (Exception e) {e.printStackTrace();}}/*** 将网络url资源文件的多个文件打包成压缩包并输出流下载** @param pathList* @param request* @param response*/public static void zipUrlToFile(List<Map<String, String>> pathList, HttpServletRequest request, HttpServletResponse response) {try {// 设置response参数并且获取ServletOutputStreamZipArchiveOutputStream zous = getServletOutputStream(response);for (Map<String, String> map : pathList) {String fileName = map.get("name");InputStream inputStream = getInputStreamFromUrl(map.get("path"));setByteArrayOutputStream(fileName, inputStream, zous);}zous.close();} catch (Exception e) {e.printStackTrace();}}private static ZipArchiveOutputStream getServletOutputStream(HttpServletResponse response) throws Exception {String outputFileName = "文件" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".zip";response.reset();response.setHeader("Content-Type", "application/octet-stream");response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(outputFileName, "UTF-8"));response.setHeader("Pragma", "no-cache");response.setHeader("Cache-Control", "no-cache");ServletOutputStream out = response.getOutputStream();ZipArchiveOutputStream zous = new ZipArchiveOutputStream(out);zous.setUseZip64(Zip64Mode.AsNeeded);return zous;}private static void setByteArrayOutputStream(String fileName, InputStream inputStream, ZipArchiveOutputStream zous) throws Exception {ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len;while ((len = inputStream.read(buffer)) != -1) {baos.write(buffer, 0, len);}baos.flush();byte[] bytes = baos.toByteArray();//设置文件名ArchiveEntry entry = new ZipArchiveEntry(fileName);zous.putArchiveEntry(entry);zous.write(bytes);zous.closeArchiveEntry();baos.close();}/*** 通过网络地址获取文件InputStream** @param path 地址* @return*/private static InputStream getInputStreamFromUrl(String path) {URL url = null;InputStream is = null;try {url = new URL(path);} catch (MalformedURLException e) {e.printStackTrace();}try {HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setDoInput(true);conn.connect();is = conn.getInputStream();} catch (IOException e) {e.printStackTrace();}return is;}
}

2、单一文件下载

2.1、本地文件下载

Controller:

@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate HttpServletResponse response;@Resourceprivate HttpServletRequest request;@GetMapping(value = "/down/file")public void downloadFileStream() {// 文件本地位置String filePath = "C:\\Users\\LiGezZ\\Desktop\\测试文件.txt";// 文件名称String fileName = "测试文件.txt";File file = new File(filePath);FileUtil.downloadFile(file, request, response, fileName);// 浏览器访问:http://x.x.x.x/test/down/file}
}

2.2、网络文件下载

注意: 通过网络请求下载时,设置的fileName一定要与http资源的后缀一致;
Controller:

@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate HttpServletResponse response;@Resourceprivate HttpServletRequest request;@GetMapping(value = "/down/file/http")public void downloadFileHttpStream() {// 文件网络地址String urlStr = "https://code.jquery.com/jquery-3.6.0.js";// 文件名称String fileName = "测试文件.js";FileUtil.downloadHttpFile(urlStr, request, response, fileName);// 浏览器访问:http://x.x.x.x/test/down/file/http}
}

3、zip压缩包批量下载

3.1、本地文件批量下载

@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate HttpServletResponse response;@Resourceprivate HttpServletRequest request;@GetMapping(value = "/down/zip")public void downloadZipStream() {List<Map<String, String>> mapList = new ArrayList<>();String basePath = "C:\\Users\\LiGezZ\\Desktop\\测试文件_";// 模拟下载本地的5个文件,分别为测试文件1~5for (int i = 1; i <= 5; i++) {Map<String, String> map = new HashMap<>();map.put("path", basePath + i + ".txt");map.put("name", "测试文件_" + i + ".txt");mapList.add(map);}FileUtil.zipDirFileToFile(mapList, request, response);// 浏览器访问:http://x.x.x.x/test/down/zip}
}

效果:

3.2、网络文件批量下载

注意: 通过网络请求下载时,设置的fileName一定要与http资源的后缀一致;

@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate HttpServletResponse response;@Resourceprivate HttpServletRequest request;@GetMapping(value = "/down/zip/http")public void downloadZipHttpByDataStream() {List<Map<String, String>> mapList = new ArrayList<>();String urlStr = "https://code.jquery.com/jquery-3.6.0.js";// 模拟下载本地的5个文件,分别为测试文件1~5for (int i = 1; i <= 5; i++) {Map<String, String> map = new HashMap<>();map.put("path", urlStr);map.put("name", "测试文件_" + i + ".js");mapList.add(map);}FileUtil.zipUrlToFile(mapList, request, response);// 浏览器访问:http://x.x.x.x/test/down/zip/http}
}

效果:

4、说三遍

下载实现的核心就是工具类代码,可以在任意的项目中进行使用;!
下载实现的核心就是工具类代码,可以在任意的项目中进行使用;!
下载实现的核心就是工具类代码,可以在任意的项目中进行使用;!

使用zip批量功能一定要配置开头提供的maven坐标
使用zip批量功能一定要配置开头提供的maven坐标
使用zip批量功能一定要配置开头提供的maven坐标

SpringBoot实现本地、网络文件下载、zip压缩包批量下载相关推荐

  1. Spring Boot 文件通过zip压缩包 批量下载

    最近项目中新增了一个需求:要求批量下载之前信息导出的word 文件,也就是批量下载. 数据是保存在ES 中,导出word 的功能也是写好的. 我的思路: 传入数据ID分别导出word 文件到服务器某个 ...

  2. 根据多个网络url打压缩包批量下载文件---java

    @RequestMapping("/toDowmNoteBygid")public void toDowmNoteBygid(List<Notes> urls , Ht ...

  3. 通过javascript在网页端生成zip压缩包并下载

    通过javascript在网页端生成zip压缩包并下载 原文:通过javascript在网页端生成zip压缩包并下载 zip.js是什么 zip.js的github项目地址:http://gildas ...

  4. JavaWeb项目文件夹生成Zip压缩包并下载到本地

    1.FileToZip接口类 /**  *  */ package com.sale.util; import java.io.BufferedInputStream;   import java.i ...

  5. python web项目导出zip文件_通过javascript在网页端生成zip压缩包并下载

    zip.js是什么 通过zip.js封装一个能在网页端生成zip文件的插件, 直接在网页中创建包含文件夹和文件的压缩包,也可以自定义名字并下载: 如何使用: 1:引用zip.js 2:引用jQuery ...

  6. java批量添加文件到ZIP压缩包并下载,文件名相同导致的异常

    做了个批量将文件添加为ZIP并下载的功能. 然后发现下载的文件数量变少了,原因是因为其中有些文件的文件名是相同的. 而ZipOutputStream流的这个方法,是无法添加相同文件名的内容. zos. ...

  7. 导出多个excel,打包成zip压缩包进行下载~~~~~~~~~

    项目需求: 将指定内容按任务分别导出excel. – 这里肯定要批量导出才行了,那么用压缩包,没毛病- 直接贴代码: /*** 以压缩包的方式下载excel* @param response* @pa ...

  8. Python网络爬虫实战(五)批量下载B站收藏夹视频

    我们除了爬取文本信息,有的时候还需要爬媒体信息,比如视频图片音乐等.就拿B站来说,我的收藏夹内的视频可能随时会失效,所以把它们下载到本地是非常保险的一件事. 对于这种大量列表型的数据,可以猜测B站收藏 ...

  9. vue 本地xlsx文件下载_前端vue下载导出excel和cvs文件

    // 导出 exportData () { this.$confirm('确认导出XXXXXX?', { confirmButtonText: '导出', cancelButtonText: '取消' ...

  10. 批量下载文件,打包成zip压缩包

    批量下载文件,用程序打成zip压缩包在下载 前台传来要下载的url数组 @RequestMapping(value = "/download",method = RequestMe ...

最新文章

  1. 获取map第一个的key和value_Hadoop学习之路(3)Map-Shuffle-Reduce详解与源码
  2. 由Qt中qApp想到的(这是单例模式么???)
  3. WordPress 主题教程 #4a:Header 模板
  4. while;do while; for循环
  5. 列表是不是python数据类型的是_在Python中,一个列表中的数据类型是否可以不相同?(回答可以or不可以)...
  6. SQL 删除重复记录,并保留其中一条
  7. 红外倒车雷达原理图_黑科技 | 5分钟看懂无人驾驶汽车和激光雷达
  8. 表格求和和计算机不一致6,(电子行业企业管理)计算机电子表格公式应用常见错误及处理(6页)-原创力文档...
  9. linux c 开发
  10. Mac配置双网卡使内外网同时访问
  11. 【可视化】使用PS将图片从白底换成其他底色时,如何保留头发边缘的发丝
  12. AD单片机九齐单片机NY8B062D SOP16九齐
  13. 2-13 monthCalendar日历控件
  14. 有道云笔记的敏捷开发实践——好文收藏吧!【转】
  15. 【Android UI设计与开发】5.底部菜单栏(二)使用Fragment实现底部菜单栏
  16. Python抓取数据具体流程
  17. 中国ORC低温余热发电系统市场深度调研报告(2023版)
  18. gurobi mac 安装
  19. SAP成都 测试面经
  20. 光伏自动化出图系统 基于C#的AutoCad二次开发

热门文章

  1. DSP原理学习笔记--第十四章--DSP算法及其实现
  2. 机器人动力学参数辨识
  3. 使用ConfuserEx加密混淆程序以及如何脱壳反编译
  4. 2019五一联赛建模心得
  5. 人大金仓数据库Centos 7 部署
  6. python 实现粒子滤波
  7. IBM X3650M4服务器拆机风扇 69Y5611 94Y6620 GFC0812DS 线序
  8. 神舟战神换cpu教程_神舟战神做工如何?神舟战神K650D-A29拆机图解教程
  9. 相关性分析和假设检验
  10. RS-485 接口 EMC 电路设计