SpringBoot返回文件让前端下载的几种方式 📅 发布时间:2026/7/5 4:36:46 👁️ 浏览次数: 01 背景在后端开发中通常会有文件下载的需求常用的解决方案有两种不通过后端应用直接使用nginx直接转发文件地址下载适用于一些公开的文件因为这里不需要授权通过后端进行下载同时进行一些业务处理本篇主要以方法2进行介绍方法2的原理步骤如下读取文件得到文件的字节流将字节流写入到响应输出流中02 一次性读取到内存通过响应输出流输出到前端GetMapping(/file/download) public void fileDownload(HttpServletResponse response, RequestParam(filePath) String filePath) { File file new File(filePath); if (!file.exists()) { throw new BusinessException(当前下载的文件不存在请检查路径是否正确); } // 将文件写入输入流 try (InputStream is new BufferedInputStream(Files.newInputStream(file.toPath()))) { // 一次性读取到内存中 byte[] buffer new byte[is.available()]; int read is.read(buffer); // 清空 response response.reset(); response.setCharacterEncoding(UTF-8); // Content-Disposition的作用告知浏览器以何种方式显示响应返回的文件用浏览器打开还是以附件的形式下载到本地保存 // attachment表示以附件方式下载 inline表示在线打开 Content-Disposition: inline; filename文件名.mp3 // filename表示文件的默认名称因为网络传输只支持URL编码的相关支付因此需要将文件名URL编码后进行传输,前端收到后需要反编码才能获取到真正的名称 response.addHeader(Content-Disposition, attachment;filename URLEncoder.encode(file.getName(), UTF-8)); // 告知浏览器文件的大小 response.addHeader(Content-Length, file.length()); OutputStream outputStream new BufferedOutputStream(response.getOutputStream()); response.setContentType(application/octet-stream); outputStream.write(buffer); outputStream.flush(); outputStream.close(); } catch (IOException e) { throw new RuntimeException(e); } }适用于小文件如果文件过大一次性读取到内存中可能会出现oom的问题02 将文件流通过循环写入到响应输出流中推荐GetMapping(/file/download) public void fileDownload(HttpServletResponse response, RequestParam(filePath) String filePath) { File file new File(filePath); if (!file.exists()) { throw new BusinessException(当前下载的文件不存在请检查路径是否正确); } // 清空 response response.reset(); response.setCharacterEncoding(UTF-8); response.addHeader(Content-Disposition, attachment;filename URLEncoder.encode(file.getName(), UTF-8)); response.setContentType(application/octet-stream); // 将文件读到输入流中 try (InputStream is new BufferedInputStream(Files.newInputStream(file.toPath()))) { OutputStream outputStream new BufferedOutputStream(response.getOutputStream()); byte[] buffer new byte[1024]; int len; //从输入流中读取一定数量的字节并将其存储在缓冲区字节数组中读到末尾返回-1 while((len is.read(buffer)) 0){ outputStream.write(buffer, 0, len); } outputStream.close(); } catch (IOException e) { throw new RuntimeException(e); } }03 从网络上获取文件并返回给前端GetMapping(/net/download) public void netDownload(HttpServletResponse response, RequestParam(fileAddress) String fileAddress, RequestParam(filename) String filename) { try { URL url new URL(fileAddress); URLConnection conn url.openConnection(); InputStream inputStream conn.getInputStream(); response.reset(); response.setContentType(conn.getContentType()); response.setHeader(Content-Disposition, attachment; filename URLEncoder.encode(filename, UTF-8)); byte[] buffer new byte[1024]; int len; OutputStream outputStream response.getOutputStream(); while ((len inputStream.read(buffer)) 0) { outputStream.write(buffer, 0, len); } inputStream.close(); } catch (IOException e) { throw new RuntimeException(e); } }04 从网络上获取文本并下载到本地GetMapping(/netDownloadLocal) public void downloadNet(RequestParam(netAddress) String netAddress, RequestParam(filepath) String filepath) { try { URL url new URL(netAddress); URLConnection conn url.openConnection(); InputStream inputStream conn.getInputStream(); FileOutputStream fileOutputStream new FileOutputStream(filepath); int byteread; byte[] buffer new byte[1024]; while ((byteread inputStream.read(buffer)) ! -1) { fileOutputStream.write(buffer, 0, byteread); } fileOutputStream.close(); } catch (IOException e) { throw new RuntimeException(e); } }05 总结一定要搞清楚InputStream和OutputStream的区别如果搞不清楚的可以和字符流进行映射InputStream - Reader,OutPutStream - Writer换成这样你就知道读取内容需要使用Reader写入需要使用Writer了。返回给前端的是输出流不需要你显示的去返回return response;这样会报错
实现Open-Lovable前端克隆网页随时随地用 Open-Lovable 是 MendableAI 团队开发的开源工具,主要功能是通过 AI 对话生成完整的 React 应用,核心能力是克隆任意网页并转化为结构清晰的 React 代码,集成了 E2B 沙箱和 Firecrawl 抓取引擎,能完整保留网页的样式和布局逻辑&am… 2026/7/5 4:35:23
企业股权结构可视化避坑指南:D3.js连线抖动/布局错位问题解决方案 企业股权结构可视化避坑指南:D3.js连线抖动与布局错位深度解决方案 在金融科技领域,将复杂的股权关系网络清晰、稳定地呈现给用户,从来都不是一件简单的事。很多开发者,尤其是那些刚刚接手企业股权穿透图、关联关系图谱这类项目的… 2026/7/5 4:34:57
零基础玩转VRoidStudio汉化插件:从安装到个性化定制完全指南 零基础玩转VRoidStudio汉化插件:从安装到个性化定制完全指南 【免费下载链接】VRoidChinese VRoidStudio汉化插件 项目地址: https://gitcode.com/gh_mirrors/vr/VRoidChinese VRoidStudio作为热门的3D角色创作工具,其全英文界面常让新手却步。本… 2026/5/17 10:40:07
一体机正在悄悄改变这5个行业 提到一体机,很多人想到的是办公电脑。但你可能没注意到,一体机正在进入越来越多的行业,改变着这些行业的日常运作方式。 一、政务窗口:从“排队等候”到“即来即办” 过去去政务大厅办事,排队是常态。窗口工作人员在传… 2026/7/5 4:35:16
G-Eval突破性实践:GPT-4驱动的NLG评估如何实现人机对齐创新 G-Eval突破性实践:GPT-4驱动的NLG评估如何实现人机对齐创新 【免费下载链接】geval Code for paper "G-Eval: NLG Evaluation using GPT-4 with Better Human Alignment" 项目地址: https://gitcode.com/gh_mirrors/ge/geval 在自然语言生成技术飞… 2026/7/5 4:33:16
6款实用降AI率软件 合规程度拉满 写论文时总担心AI生成痕迹太重?别慌,这里整理了6款超实用的免费论文降AI率工具,堪称解决AI痕迹问题的"效率利器"。它们能有效识别并消除AI生成特征,降痕效果显著,帮你轻松通过审核,彻底告别高AI率… 2026/7/5 4:31:16
3个高效文件同步场景解析:ChoEazyCopy实战应用指南 3个高效文件同步场景解析:ChoEazyCopy实战应用指南 【免费下载链接】ChoEazyCopy Simple and powerful RoboCopy GUI 项目地址: https://gitcode.com/gh_mirrors/ch/ChoEazyCopy 还在为复杂的RoboCopy命令行参数而头疼吗?ChoEazyCopy作为RoboCop… 2026/7/5 4:31:16
原来碳晶板集成墙板有这么多品牌,到底该怎么选? 在装修时,碳晶板集成墙板因安装便捷、风格多样等优势,受到不少消费者青睐。面对众多品牌,我们该如何选择呢?下面为大家提供一些参考。环保性能是关键环保是装修的重要考量因素。像康品集成墙板,采用木塑材质复合而成&a… 2026/7/5 4:29:15
抖店1688选品中心怎么用新手怎么筛一件代发货源 抖店1688选品中心怎么用?新手怎么筛一件代发货源 抖店新手做无货源,最容易卡在选品:1688 商品很多,但不是所有货源都适合抖店一件代发。选错货源后,后面会出现缺货、发货慢、售后高、利润低等问题。 所以使用 1688 选品… 2026/7/5 4:29:15
6个月转型AI工程师:实战路径与核心技能 1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公… 2026/7/5 0:01:32
TPAFE0808与PIC18F87K22的多通道信号采集方案 1. 项目背景与核心需求在工业自动化、医疗设备和科研仪器等领域,多通道信号采集与系统监测是基础且关键的技术需求。传统方案往往面临通道数量不足、信号调理复杂、系统集成度低等问题。TPAFE0808作为一款8通道模拟前端芯片,与PIC18F87K22微控制器的组合… 2026/7/5 0:01:32
STC3115与PIC18LF26K80构建高精度电池管理系统 1. STC3115与PIC18LF26K80在电池管理系统中的核心价值在现代电子设备中,电池管理系统(BMS)的重要性不亚于设备的核心处理器。STC3115作为一款高精度电池电量监测IC,与PIC18LF26K80微控制器的组合,构成了一个既能精确监控又能智能管理的完整解… 2026/7/5 0:05:36
6个月转型AI工程师:实战路径与核心技能 1. 项目概述:6个月转型AI工程师的可行性路径在2023年大模型技术爆发的背景下,AI工程师岗位需求同比增长217%(LinkedIn数据)。不同于传统算法工程师需要3-5年培养周期,现代AI工程师更侧重工程化落地能力。我在硅谷科技公… 2026/7/5 0:01:32
TPAFE0808与PIC18F87K22的多通道信号采集方案 1. 项目背景与核心需求在工业自动化、医疗设备和科研仪器等领域,多通道信号采集与系统监测是基础且关键的技术需求。传统方案往往面临通道数量不足、信号调理复杂、系统集成度低等问题。TPAFE0808作为一款8通道模拟前端芯片,与PIC18F87K22微控制器的组合… 2026/7/5 0:01:32
STC3115与PIC18LF26K80构建高精度电池管理系统 1. STC3115与PIC18LF26K80在电池管理系统中的核心价值在现代电子设备中,电池管理系统(BMS)的重要性不亚于设备的核心处理器。STC3115作为一款高精度电池电量监测IC,与PIC18LF26K80微控制器的组合,构成了一个既能精确监控又能智能管理的完整解… 2026/7/5 0:05:36