当前位置: 首页 > news >正文

SpringBoot返回文件让前端下载的几种方式

01 背景

在后端开发中,通常会有文件下载的需求,常用的解决方案有两种:

  1. 不通过后端应用,直接使用nginx直接转发文件地址下载(适用于一些公开的文件,因为这里不需要授权)
  2. 通过后端进行下载,同时进行一些业务处理

本篇主要以方法2进行介绍,方法2的原理步骤如下:

  1. 读取文件,得到文件的字节流
  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);// 清空 responseresponse.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("当前下载的文件不存在,请检查路径是否正确");}// 清空 responseresponse.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;//从输入流中读取一定数量的字节,并将其存储在缓冲区字节数组中,读到末尾返回-1while((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 总结

一定要搞清楚InputStreamOutputStream的区别,如果搞不清楚的,可以和字符流进行映射,InputStream -> Reader,OutPutStream -> Writer,换成这样你就知道读取内容需要使用Reader,写入需要使用Writer了。

返回给前端的是输出流,不需要你显示的去返回(return response;),这样会报错

相关文章:

SpringBoot返回文件让前端下载的几种方式

01 背景 在后端开发中,通常会有文件下载的需求,常用的解决方案有两种: 不通过后端应用,直接使用nginx直接转发文件地址下载(适用于一些公开的文件,因为这里不需要授权)通过后端进行下载&#…...

论述数据、数据库、数据库管理系统、数据库系统的概念。

数据是指描述事物特征的符号记录,可以是数字、文字、图像、音频等形式。数据在现代社会中广泛存在于各个领域,对于组织和管理数据,提供数据的可靠性、一致性和安全性至关重要。 数据库是一个有组织的数据集合,它存储在计算机系统…...

【深度学习基础之多尺度特征提取】多尺度卷积神经网络(MS-CNN)是如何在深度学习网络中提取多尺度特征的?附代码(二)

【深度学习基础之多尺度特征提取】多尺度卷积神经网络(MS-CNN)是如何在深度学习网络中提取多尺度特征的?附代码(二) 【深度学习基础之多尺度特征提取】多尺度卷积神经网络(MS-CNN)是如何在深度…...

企业AAA认证的好处

体系认证#ISO三体系认证 #三体系认证好处 #企业双软认证好处 #ISO体系认证有哪些#体系认证办理流程及费用#招投标#招投标必备资质 企业信用评级AAA认证 办理条件及流程! 一、企业申请3A认证好处有哪些? 1.提高企业信誉: 拥有3A企业信用等级证书意味…...

PyTorch AMP 混合精度中grad_scaler.py的scale函数解析

PyTorch AMP 混合精度中的 scale 函数解析 混合精度训练(AMP, Automatic Mixed Precision)是深度学习中常用的技术,用于提升训练效率并减少显存占用。在 PyTorch 的 AMP 模块中,GradScaler 类负责动态调整和管理损失缩放因子&…...

分数阶傅里叶变换代码 MATLAB实现

function Faf myfrft(f, a) %分数阶傅里叶变换函数 %输入参数: %f:原始信号 %a:阶数 %输出结果: %原始信号的a阶傅里叶变换N length(f);%总采样点数 shft rem((0:N-1)fix(N/2),N)1;%此项等同于fftshift(1:N),起到翻…...

腾讯云OCR在制造业的应用:内存模组产品识别实战指南

腾讯云OCR在制造业的应用 一、 背景二、 腾讯云OCR技术概述三、 内存模组产品识别需求四、基于腾讯云OCR的内存模组产品识别4.1、准备工作4.2、API调用与代码实现 五、 代码示例六、 应用场景七、 总结 一、 背景 制造业在产品识别环节经历着前所未有的挑战。传统的依赖人工进…...

基于STM32F1的基本定时器的原理

一,基本定时器原理 1,进入数据手册,了解基本定时器的主要特征 2,看懂理解基本定时器框图 3,查阅2.3章中的存储器映像以及时钟树就可以知道定时器是挂载在哪个总线下,从而知道对应是时钟频率 4,…...

Adobe Acrobat Pro DC 2023 下载安装教程,附详细图文

简介: Adobe Acrobat Pro DC 2023 是由 Adobe 公司推出的一款全面的 PDF 编辑、查看和管理软件。这款软件无论是个人用户还是企业级用户,都可以凭借其强大的功能满足不同的需求。作为一款业内领先的 PDF 处理工具,Adobe Acrobat Pro DC 不仅…...

活动预告 |【Part1】 Azure 在线技术公开课:迁移和保护 Windows Server 和 SQL Server 工作负载

课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft 云技术的了解。参加我们举办的“迁移和保护 Windows Server 和 SQL Server 工作负载”活动,了解 Azure 如何为将工作负载…...

根据 el-dialog 的高度动态计算 el-table 的高度

根据 el-dialog 的高度动态计算 el-table 的高度&#xff0c;可以使用 Vue 的 ref 和生命周期钩子来实现。以下是一个实现方案&#xff1a; 首先&#xff0c;给 el-dialog 和 el-table 添加 ref&#xff1a; <el-dialogv-model"testInstrumentDialogVisible"tit…...

算法解析-经典150(双指针、滑动窗口)

文章目录 双指针1.验证回文串1.答案2.思路 2.判断子序列1.动态规划解法2.双指针 3.两数之和 II - 输入有序数组1.答案2.思路 4.盛最多水的容器1.答案2.思路 5.三数之和1.答案2.思路 滑动窗口1.长度最小的子数组1.答案2.思路 2.无重复字符的最长子串1.答案2.思路 3.最小覆盖子串…...

Postman[2] 入门——界面介绍

可参考官方 文档 Postman 导航 | Postman 官方帮助文档中文版Postman 拥有各种工具、视图和控件&#xff0c;帮助你管理 API 项目。本指南是对 Postman 主要界面区域的高级概述&#xff1a;https://postman.xiniushu.com/docs/getting-started/navigating-postman 1. Header&a…...

GAMES101学习笔记(一):Overview 计算机图形学概述

文章目录 关于计算机图形学本课程讨论的话题光栅化曲线和网格光线追踪动画/仿真 课程大纲CG vs CV图形学的依赖学科线性代数回顾 课程资源&#xff1a;GAMES101-现代计算机图形学入门-闫令琪 Lec1 ~ Lec2 学习笔记&#xff1a; Lecture 01 &#xff1a;Overview of Computer G…...

iOS 18手机不越狱玩MC java版---PojavLauncher

环境 手机&#xff1a; iPhone SE 3 iOS: 18.1.1 电脑操作系统&#xff1a;macOS Sequoia 15.1.1 步骤 电脑上安装altstore https://altstore.io/ 直接下载自己操作系统对应的版本即可。 安装altstore到手机 以下是我记忆中的步骤&#xff0c;关键步骤我提一下 手机连接…...

uni-app开发-习惯养成小程序/app介绍

目录 一:功能概述 二:功能部分代码和截图 一:功能概述 1 习惯目标生成 创建习惯:用户可以添加新的习惯目标,每个习惯可以包含名称、描述、图标、目标天数。 关联习惯完成:用户通过设定达成目标以后,生成习惯养成记录。 2 习惯打卡 简单快捷的打卡:提供一个直观的界面…...

服务器迁移中心——“工作组迁移”使用指南

简介 服务器迁移中心&#xff08;Server Migration Center&#xff0c;简称SMC&#xff09;是阿里云提供给您的迁移平台。专注于提供能力普惠、体验一致、效率至上的迁移服务&#xff0c;满足您在阿里云的迁移需求。 工作组迁移是SMC的一项功能&#xff0c;提供标准化迁移流程…...

下载离线的瓦片图是做了模糊处理嘛?

问题&#xff1a; 1.下载离线的瓦片图是做了模糊处理嘛&#xff1f; 2.怎么加载自己的离线瓦片图比实际图片模糊了很多&#xff1f;啊 3.同层级的图片都比实际的图片模糊 原因&#xff1a;https://zhuanlan.zhihu.com/p/389945647 可以尝试下略微优化下&#xff1a; 1.降低…...

日志聚类算法 Drain 的实践与改良

在现实场景中&#xff0c;业务程序输出的日志往往规模庞大并且类型纷繁复杂。我们在查询和查看这些日志时&#xff0c;平铺的日志列表会让我们目不暇接&#xff0c;难以快速聚焦找到重要的日志条目。 在观测云中&#xff0c;我们在日志页面提供了聚类分析功能&#xff0c;可以…...

git 问题解决记录

在用git上传文件到仓库中出现了2个问题 第一个问题&#xff1a; 需要修改git的代理端口与电脑自己的代理服务器设置中的端口和VPN的端口保持一致&#xff0c; 比如我的端口是7897&#xff0c;就设置 git config --global http.proxy http://127.0.0.1:7897 git config --glo…...

Node Exporter常用Prometheus指标

Node Exporter 是一个常用的 Prometheus 导出器&#xff0c;用于采集主机操作系统层面的指标。以下是 Node Exporter 中一些常用的指标分类和关键指标&#xff1a; 1. CPU 相关指标 常用指标&#xff1a; CPU 使用率 rate(node_cpu_seconds_total{mode!"idle"}[5m]…...

golang 编程规范 - 项目目录结构

原文&#xff1a;https://makeoptim.com/golang/standards/project-layout 目录结构 Go 目录 cmdinternalpkgvendor 服务端应用程序目录 api Web 应用程序目录 web 通用应用程序目录 buildconfigsdeploymentsinitscriptstest 其他目录 assetsdocsexamplesgithooksthird_par…...

【ArcGISPro/GeoScenePro】裁剪和打包栅格数据

检查并处理扫描地图 数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 使用标准相机或扫描仪创建的数字影像通常存储在 RGB 颜色模型中,这意味着这些影像将由红色、绿色和蓝色三个栅格组成。 此扫描地图在提供给您之前已在坐标系…...

数据库新建用户后(Host:%),报错:localhost无法连接

存在问题 在给数据库&#xff08;MySQL、MariaDB等&#xff09;创建了新的用户名&#xff08;eg&#xff1a;maxscale&#xff09;后&#xff0c;无法使用新用户名登录&#xff0c;并报如下错误&#xff1a;ERROR 1045 (28000): Access denied for user maxscalelocalhost (us…...

[文献阅读] Reducing the Dimensionality of Data with Neural Networks

文章目录 摘要Abstract:RBM自编码器深层自编码器初始化展开微调 实验总结 摘要 Reducing the Dimensionality of Data with Neural Networks Reducing the Dimensionality of Data with Neural Networks | Science 使用神经网络降低数据的维度 由Hinton在2006年于Science上发…...

Sublime Text4 4189 安装激活【 2025年1月3日 亲测可用】

-----------------测试时间2025年1月3日------------------- 下载地址 官方网址&#xff1a;https://www.sublimetext.com 更新日志&#xff1a;https://www.sublimetext.com/download V4189 64位&#xff1a;https://www.sublimetext.com/download_thanks?targetwin-x64 ....…...

自相关性的数值越接近于1说明什么

自相关性数值越接近于 1&#xff0c;通常表明以下几点&#xff1a; 1. 强正相关 - 自相关系数接近于 1 表示当前值与其滞后值之间存在强正相关关系。这意味着&#xff0c;当当前值较高时&#xff0c;之前的值也倾向于较高&#xff0c;反之亦然。 2. 时间序列的持久性 - 如果…...

【ArcGIS Pro微课1000例】0064:栅格目录、栅格数据集、镶嵌数据集

一、栅格目录与栅格数据集 1. 定义 栅格目录:是一个用于管理和组织栅格数据集的结构,通常包含多个栅格数据集的元数据和索引信息。它相当于一个文件夹,里面可以存放多个栅格文件。可以将工作空间转栅格目录。 栅格数据集:是指单个的栅格数据文件,包含了具体的空间数据,…...

单片机-静动态数码管实验

P0控制数码管 &#xff0c;P0低电平 P1,P2,P3高电平 1、静态数码管 需求&#xff1a;数码管显示0&#xff0c;即让p0端口输出数字0的段码0x3f(共阴) #include "reg52.h" typedef unsigned int u16; typedef unsigned char u8; //数码管显示数字的数组 共阴极 …...

学术写作中的各种流程图如何利用Kimi进行辅助构建?

目录 1.学术论文中的流程图 2.一些小实践 3.论文中严谨的实践流程 近期小编在思考使用AI工具制作流程图和思维导图&#xff0c;结果发现Kimi现在支持流程图了&#xff0c;Kimi在学术写作中的应用变得更加广泛和深入。随着AIGC技术的不断进步&#xff0c;Kimi的功能将更加强大…...

halcon中图像处理及图像滤波

图像滤波简介 图像滤波的方法主要分为两大类:空间域方法和频域方法。 空间域方法是以对图像的像素直接进行处理为基础,包括均值滤波、中值滤波、高斯滤波等;频域方法则是以修改图像在傅里叶变换空间的值为基础的,包括高通滤波、低通滤波、同态滤波等。 1.空间域图像滤波 图…...

【pyqt】(三)designer

designer ui设计 在学习后续的代码之前&#xff0c;我们可以先学习一下designer这款工具&#xff0c;在安装软件的时候我们有提到过&#xff0c;其具体位置在虚拟环境根目录下的\Lib\site-packages\PySide6文件夹中。对于新手而言&#xff0c;使用这种可视化的工具可以帮助我们…...

微服务之服务治理——Eureka

CAP原则: Consistency(一致性):在分布式系统中的所有数据备份&#xff0c;在同一时刻是否同样的值。&#xff08;等同于所有节点访问同一份最新的数据副本&#xff09; Availability(可用性):在集群中一部分节点故障后&#xff0c;集群整体是否还能响应客户端的读写请求…...

JS 中 json数据 与 base64、ArrayBuffer之间转换

JS 中 json数据 与 base64、ArrayBuffer之间转换 json 字符串进行 base64 编码 function jsonToBase64(json) {return Buffer.from(json).toString(base64); }base64 字符串转为 json 字符串 function base64ToJson(base64) {try {const binaryString atob(base64);const js…...

C#实现画图,及实现图像运动,C#中GDI+图形图像技术(Graphics类、Pen类、Brush类)C#之快速入门GDI+绘图 C#实现快速画图功能

下载源码 <-------- 在C#的世界里&#xff0c;GDI如同一位多才多艺的艺术家&#xff0c;以其强大的绘图能力&#xff0c;让开发者能够轻松地在应用程序中挥洒创意&#xff0c;绘制出丰富多彩的图形世界。GDI不仅支持基本的几何图形绘制&#xff0c;还能处理复杂的图像处理任…...

32单片机从入门到精通之开发环境——调试工具(七)

在人生的道路上&#xff0c;困难和挫折时常会出现。但是我们不能因此放弃&#xff0c;而是要坚持努力&#xff0c;克服困难&#xff0c;实现自己的梦想。成功不是一蹴而就的&#xff0c;它需要付出大量的努力和坚持不懈的精神。每一次的失败都是一次宝贵的经验&#xff0c;它能…...

多光谱图像的处理和分析方法有哪些?

一、预处理方法 1、辐射校正&#xff1a; 目的&#xff1a;消除或减少传感器本身、大气条件以及太阳光照等因素对多光谱图像辐射亮度值的影响&#xff0c;使得图像的辐射值能够真实反映地物的反射或发射特性。 方法&#xff1a;包括传感器校正和大气校正。传感器校正主要是根…...

电脑主机后置音频插孔无声?还得Realtek高清晰音频管理器调教

0 缘起 一台联想电脑&#xff0c;使用Windows 10 专业版32位&#xff0c;电脑主机后置音频插孔一直没有声音&#xff0c;所以音箱是接在机箱前面版的前置音频插孔上的。 一天不小心捱到了音箱的音频线&#xff0c;音频线头断在音频插孔里面了&#xff0c;前置音频插孔因此用不…...

2412C++,自动注册

原文 注册器实现 示例代码 #pragma once #include <type_traits> #include <iostream> template<typename _Type> struct odr{inline static auto use []{ //[1]std::cout << __PRETTY_FUNCTION__ << std::endl;//在这里利用宏,注册(类名,T)…...

C#对线程同步的应用

什么是线程同步&#xff1f;线程同步的应用场景有哪些&#xff1f;在C#中有哪些线程同步方式&#xff1f;下面对这些问题做一个总结&#xff0c;让大家在面试的时候遇到这些问题能够游刃有余。 线程同步是指在多线程环境下&#xff0c;多个线程同时访问共享资源时&#xff0c;确…...

需求上线,为什么要刷缓存?

在需求上线的过程中&#xff0c;刷缓存主要有以下几个重要原因&#xff1a; 一、保证数据的准确性 旧数据残留问题 缓存是为了加快数据访问速度而存储的数据副本。在需求更新后&#xff0c;之前缓存中的数据可能已经不符合新的业务逻辑。例如&#xff0c;一个电商网站修改了商…...

Docker学习相关笔记,持续更新

如何推送到Docker Hub仓库 在Docker Hub新建一个仓库&#xff0c;我的用户名是 leilifengxingmw&#xff0c;我建的仓库名是 hello_world。 在本地的仓库构建镜像&#xff0c;注意要加上用户名 docker build -t leilifengxingmw/hello_world:v1 .构建好以后&#xff0c;本地会…...

手持PDA终端,提升零售门店管理效率

随着科技的不断进步和零售行业的持续发展&#xff0c;手持PDA终端的应用将会越来越广泛。它将不断融合更多先进的技术和功能&#xff0c;为零售门店管理带来更加便捷、高效、智能的解决方案。 手持PDA终端是集成了数据处理、条码扫描、无线通信等多种功能于一体的便携式设备‌…...

Spring实现Logback日志模板设置动态参数

版权说明&#xff1a; 本文由博主keep丶原创&#xff0c;转载请保留此块内容在文首。 原文地址&#xff1a; https://blog.csdn.net/qq_38688267/article/details/144842327 文章目录 背景设计日志格式实现配置动态取值logback-spring.xml 相关博客 背景 多个单体服务间存在少量…...

AI Infra

文章目录 关于 InfraAI Infra的核心思想 组成部分硬件软件网络云服务监控与优化安全与合规 关键里程碑未来展望 关于 Infra 在大模型中&#xff0c;“infra” 是 “infrastructure” 的缩写&#xff0c;指的是支持大模型训练和部署的技术基础设施。以下是其主要组成部分&#…...

【每日学点鸿蒙知识】RelativeContainer组件、List回弹、Flutter方法调用、Profiler工具等

1、RelativeContainer组件auto对齐规则&#xff1f; 当height设置为auto&#xff0c;这时候为什么子组件设置 top:{anchor: "__container__",align: VerticalAlign.Top}后auto就不生效了呢&#xff0c;anchor锚点不是默认top对齐的吗&#xff1f; 这是为了避免二次…...

springboot集成qq邮箱服务

springboot集成qq邮箱服务 1.获取QQ邮箱授权码 1.1 登录QQ邮箱 1.2 开启SMTP服务 找到下图中的SMTP服务区域&#xff0c;如果当前账号未开启的话自己手动开启。 1.3 获取授权码 进入上图中的【管理服务】后&#xff1a;在【安全设置中生成授权码】,也可以直接点击【继续生成…...

【重庆】《政务数字化应用费用测算规范》(T/CDCIDA 001—2023)-省市费用标准解读系列36

《政务数字化应用费用测算规范&#xff08;报批稿&#xff09;》于2023年11月18日实施&#xff0c;本文件按照GB/T 1.1-2020给出的规则起草&#xff0c;主要适用于重庆政务数字化应用项目的费用测算。我司基于专业第三方信息化项目造价机构角度&#xff0c;从标准创新点、定制软…...

linux-centos8-安装make

参考&#xff1a; CentOS 8中 更新或下载时报错&#xff1a;为仓库 ‘appstream‘ 下载元数据失败 : Cannot prepare internal mirrorlist_errors during downloading metadata for repository -CSDN博客 https://blog.csdn.net/lxcw_sir/article/details/140185068 Linux报错…...

springboot3 ThreadPoolTaskExecutor 和 Executors 线程池优化

在 Spring Boot 3 中,可以通过 ThreadPoolTaskExecutor 和 Executors 等方式创建和管理线程池。以下是基于 Spring Boot 的线程池创建工具的详细说明与实现: 一、使用 ThreadPoolTaskExecutor 创建线程池 Spring 提供了 ThreadPoolTaskExecutor,用于管理线程池。它支持灵活…...