通俗易懂【Springboot】 单文件下载和批量下载(多个文件合成一个压缩包下载)
文章目录
- 一.单文件下载
- 1.简单理解文件下载
- 2.单文件下载的具体代码实现
- 3.测试
- 4.单文件下载整体代码
- 二.多文件批量下载(多个文件合成一个压缩包下载)
- 1.多文件下载的实现方式,这里使用了ZipOutputStream
- 2.具体代码实现
- 3.测试
- 4.文件批量下载(多文件合成一个压缩包)完整代码
一.单文件下载
1.简单理解文件下载
文件下载,是从服务器下载到本地电脑。 文件下载的原理,首先通过IO流将服务器的文件读取到内存里(只有将数据读到内存,电脑才可以操作数据),读取后文件数据存放在内存中,将内存中的数据通过网络发送给本地客户端的浏览器。本地客户端的浏览器接受数据,并在本地生成对应的文件。


2.单文件下载的具体代码实现
- 接受请求,参数
path是文件在服务器的路径(通常路径会存在sql表里,通过查表获取,这里是为了测试),HttpServletResponse要通过HttpServletResponse来实现客户端和服务器通信的响应部分(将响应头和文件数据返回后端)。
@RequestMapping("/download")public void downLoad(String path, HttpServletResponse response) throws UnsupportedEncodingException {
- 设置响应头信息(规定死的)
响应头信息代表的含义:ContentType,互联网媒体类型,也叫做MIME类型,Http在传输数据对象时会为他们打上MIME的数据格式标签,区分数据类型
常见ContentType,text/html,HTML文本application/json, 键值对的json数据格式application/octet-stream,是一种二进制数据流的文件类型,通常用于文件传输。它表示文件中包含的数据是二进制数据,而不是文本。由于它是一种通用类型,因此它可用于处理各种类型的文件,如图像,音频和视频文件。Content-Disposition
指定响应头的展示方式,主要体现在:
* 指定下载文件的文件名和保存方式。如"attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")中的filename=xxx指定了后的文件的文件名和格式
* 控制浏览器的行为。如"attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")的attachment,指定浏览器以附件的形式展示文件,即指定浏览器下载文件而不是打开文件,如果设置为inline,则是在浏览器打开文件。如果没有filename浏览器会出现保存为的对话框。- 常见值
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="XXX"
* 设置响应头代码
response.reset();response.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));response.setCharacterEncoding("utf-8");//设置编码格式为utf-8response.setContentLength((int)file.length());//响应数据长度response.setContentType("application/octet-stream");
-
通过IO流读取文件并将数据返回给浏览器
try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));OutputStream outputStream = response.getOutputStream();)是try-with-resource的语法格式,作用为try块退出时,会自动调用在()中的bis,outputStream资源的close()方法,自动关闭IO资源。(不用手动关闭了代码书写复杂度降低)
获取response的输出流OutputStream,从文件的InputStream输入流读取数据到内存,然后通过输出流写入。

- 代码示例
try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));OutputStream outputStream = response.getOutputStream();){byte[] bytes = new byte[1024];int i=0;while((i=bis.read(bytes))!=-1){outputStream.write(bytes,0,i);}}catch (Exception e){e.printStackTrace();}
3.测试

4.单文件下载整体代码
@RequestMapping("/download")public void downLoad(String path, HttpServletResponse response) throws UnsupportedEncodingException {File file=new File(path);String fileName= file.getName();response.reset();response.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));response.setCharacterEncoding("utf-8");response.setContentLength((int)file.length());response.setContentType("application/octet-stream");System.out.println("filename:"+fileName);try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));OutputStream outputStream = response.getOutputStream();){byte[] bytes = new byte[1024];int i=0;while((i=bis.read(bytes))!=-1){outputStream.write(bytes,0,i);}}catch (Exception e){e.printStackTrace();}}
二.多文件批量下载(多个文件合成一个压缩包下载)
1.多文件下载的实现方式,这里使用了ZipOutputStream
- 介绍
ZipOutputStream-
ZipOutputStream使用流程,

-
使用示例
-
//初始化,test.zip是写入压缩包的名称
ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream("test.zip"));
//创建一个名称为test.txt新的条目,一般压缩包中有很多文件,新条目相当于创建新文件
zipOutputStream.putNextEntry(new ZipEntry("test.txt"));
//写入具体内容
zipOutputStream.write("Hello World".getBytes());
//关闭条目
zipOutputStream.closeEntry();
//关闭整体压缩输出流
zipOutputStream.close();
2.具体代码实现
- 模拟选中多文件(可以通过前端传)
List<String> pathList=new ArrayList<>();pathList.add("xxx.txt");pathList.add("xxx.txt");pathList.add("xxx.txt");
- 设置响应头
response.reset();response.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode("1.zip", "UTF-8"));response.setCharacterEncoding("utf-8");
- 初始化
ZipOutputStream
try(ZipOutputStream zipOutputStream=new ZipOutputStream(new BufferedOutputStream(response.getOutputStream())))
- 遍历
List,从中读取要批量下载的文件路径
for(String pathName:pathList)
- 对每个批量下载的文件,都在
zipOutputStream(压缩包中创建对应的条目,及对应的文件)putNextEntry(new ZipEntry(fileName))创建和下载文件相同名称的文件条目。把每个下载的文件内容写入到zipOutputStream中的条目中,关闭条目,然后循环。
File file =new File(pathName);String fileName=file.getName();zipOutputStream.putNextEntry(new ZipEntry(fileName));try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file))){byte[] bytes = new byte[1024];int i=0;while((i=bis.read(bytes))!=-1){zipOutputStream.write(bytes,0,i);}zipOutputStream.closeEntry();
3.测试

4.文件批量下载(多文件合成一个压缩包)完整代码
@GetMapping("/downloadlist")public void downLoadList( HttpServletResponse response ) throws UnsupportedEncodingException {List<String> pathList=new ArrayList<>();pathList.add("xxx.txt");pathList.add("xxx.txt");pathList.add("xxx.txt");response.reset();response.setHeader("Content-Disposition","attachment; filename=" + URLEncoder.encode("1.zip", "UTF-8"));response.setCharacterEncoding("utf-8");response.setContentType("application/octet-stream");try(ZipOutputStream zipOutputStream=new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()))){for(String pathName:pathList){File file =new File(pathName);String fileName=file.getName();zipOutputStream.putNextEntry(new ZipEntry(fileName));try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file))){byte[] bytes = new byte[1024];int i=0;while((i=bis.read(bytes))!=-1){zipOutputStream.write(bytes,0,i);}zipOutputStream.closeEntry();}catch (Exception e){e.printStackTrace();}}}catch (Exception e){e.printStackTrace();}}
相关文章:
通俗易懂【Springboot】 单文件下载和批量下载(多个文件合成一个压缩包下载)
文章目录一.单文件下载1.简单理解文件下载2.单文件下载的具体代码实现3.测试4.单文件下载整体代码二.多文件批量下载(多个文件合成一个压缩包下载)1.多文件下载的实现方式,这里使用了ZipOutputStream2.具体代码实现3.测试4.文件批量下载&…...
CnOpenData中国行政区划shp数据
一、数据简介 中国行政区划数据是重要的基础地理信息数据,目前不同来源的全国行政区划数据非常多,但能够开放获取的高质量行政区域数据少之又少。基于此,锐多宝的地理空间制作一套2013-2023年可开放获取的高质量行政区划数据。该套数据以2022…...
GPT-4零失误通关大厂模拟面试,offer拿到手软?与AGI首次接触
来源: FoxyearMeta “GPT-4可被视作AGI (通用人工智能)的早期版本。” 如若从他人口中说出,或许是无稽之谈—— 但是由微软雷蒙德研究院机器学习理论组负责人万引大神Sbastien Bubeck与2023新视野数学奖得主Ronen Eldan、2023新晋斯隆研究奖得…...
Hardhat 环境搭建及教程示例
一.安装node.js curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash nvm install 18 nvm use 18 nvm alias default 18 npm install npm --global # Upgrade npm to the latest version 二. 安装hardhat 2.1 创建hardhat安装目录 mkdir hard…...
复杂链表的复制-剑指Offer35-java
一、题目描述 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。 示例 1: 输入:head [[7,null],[13,…...
【Linux】进程理解与学习Ⅰ-进程概念
环境:centos7.6,腾讯云服务器Linux文章都放在了专栏:【Linux】欢迎支持订阅🌹相关文章推荐:【Linux】冯.诺依曼体系结构与操作系统进程概念什么是进程?进程是什么?我们打开任务管理器可以看到有…...
WebKitX ActiveX 6.0 X86 Crack
WebKitX ActiveX将 Chromium Embedded Framework (CEF3) 包装到一个进程外的 ActiveX 组件中,以便与 OLE/COM 语言一起使用。Chromium Embedded Framework 封装了 WebKit Blink HTML5 Renderer 和 Google V8 JavaScript Engine。这是一个用于商业用途的生产级稳定组…...
开源项目:数据库表结构生成文档工具
目录 一、软件介绍 二、技术框架 三、功能介绍 四、代码展示 1、获取数据库信息部分代码 2、导出Html文档代码 五、运行效果 六、项目开源地址 一、软件介绍 今天给大家分享我自己编写的数据库表结构文档生成工具,方便大家在实际开发当中,可以很方便导出…...
spring的两种拦截器HandlerIntercepter和MethodIntercepter
介绍 Spring有两种拦截器提供给我们使用,一种是HandlerIntercepter,另一种是MethodIntercepter。这两种的来源不同,实现方式也不同,具体的下面来看一下。 HandlerIntercepter 来源 来源于spring-webmvc包 HandlerIntercepter拦…...
初级算法-字符串
主要记录算法和数据结构学习笔记,新的一年更上一层楼! 初级算法-字符串一、反转字符串二、反转字符串(二)三、替换空格四、翻转字符串里的单词五、左旋转字符串六、实现 strStr()七、重复的子字符串字符串中元素只能是字符String…...
华为OD机试题 - 寻找目标字符串(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为…...
删除Terminating状态的namespace:cattle-system
这里以cattle-system为例!执行删除命令后namespace(也是用其他k8s object)仍然存在,首先执行 kubectl edit namespace cattle-system 查看是否存在spec.finalizers: kubernetes,如: spec: finalizers:…...
MiniOB 并发B+树实现解析
MiniOB 是 OceanBase 联合华中科技大学推出的一款用于教学的小型数据库系统,希望能够帮助数据库爱好者系统性的学习数据库原理与实战。 B 树介绍 B 树是传统数据库中常见的索引数据结构,比如MySQL、PostgreSQL都实现了B树索引。B 树是一个平衡多叉树&am…...
SpringCloud负载均衡服务调用——Ribbon
Ribbon 本专栏学习内容来自尚硅谷周阳老师的视频 有兴趣的小伙伴可以点击视频地址观看 简介 Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算…...
各种邮箱服务软件对比
1.宝塔邮局管理器 特点:简单易用,可视化操作,小白也能搞,还有备份功能,一般足够用了 缺点:稳定性真是差,隔三差五的不能收发.没有接口,不能任意修改邮箱密码,只能管理员修改 注意要点:一定要开启ssl,否则有些邮箱给你发邮件你收不到 建议:不要入坑.坏了之后没法修复,哭都没地方…...
相机单独标定的实现过程[autoware标定]、tmp文件的查看方式
安装了autoware1.13和calibration标定包,发现实现相机单独标定的过程较为坎坷,参考了一些博主的方法,发现下面的过程更加适合自己,做个笔记。 1安装标定箱(与calibration标定包的安装并不冲突) 标定工具箱…...
4.10.1、IP 多播技术的相关基本概念
多播(Multicast,也称为组播)是一种实现 “一对多” 通信的技术,与传统单播“一对一”通信相比,多播可以极大地节省网络资源。 在因特网上进行的多播,称为 IP 多播。 1、单播 & 多播 如下所示…...
PIGOSS BSM监控国产数据库Oscar
前言神通数据库(原OSCAR数据库)是天津神舟通用数据技术有限公司(简称“神舟通用公司”)拥有自主知识产权的企业级、大型通用关系型数据库管理系统。PIGOSS BSM作为网利友联科技完全自主研发的纯国产基础 IT 架构运行状态监测平台软件…...
Spring Boot中文件上传
Spring Boot中文件上传 前言 本篇主要参考Spring官方文档,整理了Spring Boot中文件上传如何实现,以及在代码中使用RestTemplate和HttpClient两种方式实现文件上传。 创建Spring Boot项目 首先创建一个Spring Boot Web项目,使用的Spring B…...
Github上传大文件(>25MB)教程
Github上传大文件(>25MB)教程Github上传大文件(>25MB)教程安装git安装Git Large File Storage实例踩坑点1:failed to push some refs to踩坑点2:main与master踩坑点3:Failed to connect t…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
