SpringBoot实现文件下载限速

SpringBoot实现文件下载限速

在SpringBoot项目中,实现文件下载的限速功能可以有效控制服务器带宽的占用,并防止单个用户消耗过多的资源。本文将通过具体的代码示例和详细的流程解释,介绍如何在SpringBoot项目中实现文件下载的限速功能。

前言

在文件下载过程中,如果不加以控制,可能会导致服务器带宽被单个或少数用户占用,影响其他用户的访问体验。通过实现文件下载的限速,可以平衡带宽资源的使用,确保所有用户都有良好的下载体验。

实现思路

为了实现文件下载的限速,我们需要以下几个关键步骤:

  1. 创建一个工具类,用于限制下载速率。
  2. 在控制器中使用该工具类处理文件下载请求。
  3. 使用StreamingResponseBody实现流式响应,确保大文件可以逐步传输。

代码实现

步骤1:创建限速工具类

首先,我们创建一个限速工具类RateLimiter,该类包含一个方法limitDownloadSpeed,用于限制下载速率。

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @desc: 文件工具类
 * @author: shy
 * @date: 2024/06/28 11:27
 */
public class FileUtil {

    private static final int BUFFER_SIZE = 1024;

    /**
     * 文件下载限速
     *
     * @param in             输入流
     * @param out            输出流
     * @param bytesPerSecond 每秒允许下载的字节数
     * @throws IOException
     */
    public static void limitDownloadSpeed(InputStream in, OutputStream out, int bytesPerSecond) throws IOException {
        byte[] buffer = new byte[BUFFER_SIZE];
        int bytesRead;
        long bytesSent = 0;
        long startTime = System.currentTimeMillis();
        try {
            while ((bytesRead = in.read(buffer)) != -1) {
                // 将数据写入输出流
                out.write(buffer, 0, bytesRead);
                bytesSent += bytesRead;

                if (bytesSent >= bytesPerSecond) {
                    long elapsedTime = System.currentTimeMillis() - startTime;
                    if (elapsedTime < 1000) {
                        // 如果时间少于1秒,则休眠剩余时间
                        Thread.sleep(1000 - elapsedTime);
                    }
                    // 重置已发送字节计数和开始时间
                    bytesSent = 0;
                    startTime = System.currentTimeMillis();
                }
            }
        } catch (InterruptedException e) {
            // 恢复线程的中断状态
            Thread.currentThread().interrupt();
            throw new IOException("Thread was interrupted", e);
        }
    }
}

解释

  • BUFFER_SIZE:定义缓冲区大小。
  • limitDownloadSpeed:通过try-with-resources管理InputStream,根据设定的速率读取数据并写入输出流,控制传输速率。
步骤2:修改文件下载控制器

接下来,我们在控制器中使用StreamingResponseBody来实现文件下载,并调用限速工具类的方法。

import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import com.shy.admin.common.annotation.WithoutLogin;
import com.shy.common.utils.FileUtil;

/**
 * @desc: 文件下载Controller
 * @author: shy
 * @date: 2024/06/28 10:48
 */
@RestController
@RequestMapping("/file")
public class FileController {

    // 每秒允许下载的字节数(例如100KB/s)
    private static final int BYTES_PER_SECOND = 1024 * 100; 

    @WithoutLogin
    @GetMapping("/download/{filename}")
    public ResponseEntity<StreamingResponseBody> downloadFile(@PathVariable String filename) {
        // 获取要下载的文件
        File file = new File("D:\\tools\\" + filename);
        // 使用 StreamingResponseBody 实现流式响应体
        StreamingResponseBody responseBody = outputStream -> {
            try (InputStream inputStream = Files.newInputStream(file.toPath())) {
                // 调用限速方法
                FileUtil.limitDownloadSpeed(inputStream, outputStream, BYTES_PER_SECOND);
            }
        };
        // 返回 ResponseEntity,包含响应头和流式响应体
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName())
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .contentLength(file.length())
                .body(responseBody);
    }
}

解释

  • StreamingResponseBody:实现流式响应体,用于处理大文件的逐步传输。
  • responseBody:通过lambda表达式实现StreamingResponseBodywriteTo方法,在方法中使用try-with-resources管理InputStream,并调用RateLimiter的方法实现限速。

工作流程

  1. 请求处理:当客户端发送下载请求时,Spring 调用控制器方法downloadFile
  2. 创建 StreamingResponseBody:控制器方法创建StreamingResponseBody实例。
  3. 返回 ResponseEntity:控制器方法返回包含StreamingResponseBodyResponseEntity,并设置适当的响应头(如Content-DispositionContent-Type)。
  4. 调用 writeTo 方法:Spring 在准备向客户端发送响应时,调用StreamingResponseBodywriteTo方法,并传入与客户端连接的OutputStream
  5. 写入数据writeTo方法中,从文件输入流读取数据,并通过RateLimiter方法将数据写入OutputStream,同时控制传输速率。

总结

通过以上步骤,我们成功在SpringBoot项目中实现了文件下载的限速功能。核心思路是通过一个限速工具类控制数据传输速率,并使用StreamingResponseBody实现流式响应,确保大文件可以逐步传输。这种设计既能有效控制带宽资源的使用,又能提供良好的用户下载体验。

希望这篇文章对你有所帮助,如果有任何问题或建议,欢迎在评论区留言讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/769186.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TOB传输、承载网拓扑图

1、用户面&#xff1a;GNODEB>UPE>SPE>NPE>UPF>CMNET网 2、控制面&#xff1a;GNODEB>UPE>SPE>NPE>IP承载网>核心网

充分利用智慧校园人事系统,提升党政职务管理

智慧校园人事系统中的党政职务管理功能&#xff0c;是专为高校及教育机构设计的&#xff0c;旨在高效、精确地处理与党政职务相关的各类事务&#xff0c;包括职务任命、任期管理、职责分配、考核评估等&#xff0c;以信息化手段促进党务及行政工作的透明化、规范化。 该模块首先…

redis主从复制哨兵模式集群管理

主从复制&#xff1a; 主从复制是高可用Redis的基础&#xff0c;哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份&#xff0c;以及对于读操作的负载均衡和简单的故障恢复。缺陷&#xff1a;故障恢复无法自动化&#xff1b;写操作无法负载均衡&…

像学Excel 一样学 Pandas系列-创建数据分析维度

嗨&#xff0c;小伙伴们。又到喜闻乐见的Python 数据分析王牌库 Pandas 的学习时间。按照数据分析处理过程&#xff0c;这次轮到了新增维度的部分了。 老样子&#xff0c;我们先来回忆一下&#xff0c;一个完整数据分析的过程&#xff0c;包含哪些部分内容。 其中&#xff0c…

好久不见!写了一个自动截图神器~【附源码】

文章目录 前言新增功能介绍截图功能快捷键设置 程序设计和使用介绍操作菜单栏选择点击坐标点选择图片选择截图区域快捷键设置 表格循环次数状态栏 使用案例源代码 前言 好久没更新文章了。上一次更新是在4月16日差不多&#xff0c;也只是写了一个错误集&#xff0c;没什么太多…

【Python机器学习】模型评估与改进——在模型选择中使用评估指标

我们通常希望&#xff0c;在使用GridSearchCV或cross_val_score进行模型选择时能够使用AUC等指标。scikit-learn提供了一种非常简单的实现方法&#xff0c;那就是scoring参数&#xff0c;它可以同时用于GridSearchCV和cross_val_score。你只需要提供一个字符串&#xff0c;用于…

基于Vue的MOBA类游戏攻略分享平台

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java技术、SpringBoot框架、B/S模式、Vue.js 工具&#xff1a;MyEclipse、MySQL 系统展示 首页 用…

大模型技术在辅助学习中的应用

大模型技术在辅助学习中的应用场景非常广泛&#xff0c;以下是一些典型示例。大模型技术在辅助学习中具有广阔的应用前景&#xff0c;可以为学生提供更加个性化、智能化和高效的学习体验。随着大模型技术的不断发展&#xff0c;我们可以期待在未来看到更多创新应用。北京木奇移…

免费最好用的证件照制作软件,一键换底+老照片修复+图片动漫化,吊打付费!

这款软件真的是阿星用过的&#xff0c;最好用的证件照制作软件&#xff0c;没有之一&#xff01; 我是阿星&#xff0c;今天要给大家安利一款超实用的证件照工具&#xff0c;一键换底&#xff0c;自动排版&#xff0c;免费无广告&#xff0c;让你在家就能轻松搞定证件照&#…

强化学习的数学原理:最优贝尔曼公式

大纲 贝尔曼最优公式是贝尔曼公式的一个特殊情况&#xff0c;但其也非常重要。 本节课很重要的两个概念和一个工具&#xff1a; 工具不用多说&#xff0c;就是贝尔曼最优公式&#xff0c;概念则是 optimal state value&#xff08;最优状态价值&#xff09; 和 optimal polic…

Django开发实战(1)- 认识django

1.django 使用MTV模式&#xff0c;其实与MVC本质一样&#xff1a; model&#xff1a;业务对象和关系映射&#xff08;ORM&#xff09; template&#xff1a;客户端页面展示 view&#xff1a;业务逻辑&#xff0c;根据需求调用 2.开发相关 √ python √ html&…

鸿蒙数据防泄漏(DLP)【Data Loss Prevention Kit开发指导】

Data Loss Prevention Kit开发指导 DLP是系统提供的系统级的数据防泄漏解决方案&#xff0c;提供一种称为DLP的文件格式。后缀格式为“原始文件名&#xff08;包含原始文件后缀&#xff09;.dlp”&#xff0c;例如: “test.docx.dlp”&#xff0c;文件由授权凭证和原始文件密文…

8款你不一定知道的良心软件!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/我们使用一些流行的软件的时候&#xff0c;往往会忽略一些功能非常强大的软件&#xff0c;因为这些软件的众 多&#xff0c;都因为看不见而丢失&a…

【ACM出版-EI稳检索】第三届金融创新、金融科技与信息技术国际学术会议(FFIT 2024,7月26-28)

第三届金融创新、科技与信息技术国际学术会议&#xff08;FFIT 2024&#xff09;将于2024年07月26-28日于重庆举行。 FFIT2024 将围绕“金融创新”、"金融科技”与“信息技术”等相关最新研究领域&#xff0c;为来自国内外高等院校、科学研究所、企事业单位的专家、教授、…

Vue3Echarts写关于温湿度统计的好看折线图

在项目统计界面&#xff0c;我们离不开对Echarts的使用&#xff0c;接下来是我在做项目过程中做的一个关于温湿度统计的好看折线图&#xff0c;统计的是温度蓝色和湿度绿色&#xff0c;它们还会有告警和断电&#xff0c;分别用橘黄色和红色区分&#xff0c;以下是示例&#xff…

CesiumJS【Basic】- #056 绘制纹理填充多边形(Entity方式)-使用shader

文章目录 绘制纹理填充多边形(Entity方式)-使用shader1 目标2 代码2.1 main.ts绘制纹理填充多边形(Entity方式)-使用shader 1 目标 使用Entity方式绘制绘制纹理填充多边形 - 使用shader 2 代码 2.1 main.ts import * as Cesium from cesium;const viewer = new Cesium…

Linux系统中交叉编译opencv库

目标&#xff1a;将opencv进行交叉编译&#xff0c;使其能在rk3326板子上运行使用。 环境&#xff1a; ubuntu&#xff1a;18.04 opencv:4.5.4 opencv源码从挂网下载&#xff1a;opencv源码下载地址 交叉编译链&#xff1a;gcc-arm-10.3-linux-gun 一.环境准备 1.交叉编译链我…

【RT摩拳擦掌】如何构建RT AVB switchendpoint平台

【RT摩拳擦掌】如何构建RT AVB switch&endpoint平台 一&#xff0c;文档简介二&#xff0c;平台构建2.1 软硬件情况2.2 配置RT1170 AVB端点2.2.1 1块MIMXRT1170开发板做talker配置2.2.2 2块MIMXRT1170开发板做listener配置 2.3 AVB Switch 配置2.3.1 MOTU AVB Switch2.3.2 …

Ansys Zemax|场曲跟畸变图的前世今生

实现 OpticStudio通过在X和Y方向&#xff08;弧矢和子午方向&#xff09;的傍轴光线追踪确定近轴图像平面的Z坐标&#xff0c;并测量该近轴焦平面与系统图像平面的Z坐标之间的距离。 切向数据是沿Z轴从图像平面到近轴图像平面在切向&#xff08;YZ&#xff09;平面测量的距离…

【LeetCode刷题】3099.哈沙德数

题目链接 3099. 哈沙德数 - 力扣&#xff08;LeetCode&#xff09; 实现代码 int sumOfTheDigitsOfHarshadNumber(int x) {int sum 0;for(int temp x; temp; temp / 10)sum temp % 10;return x%sum ? -1 : sum; }
最新文章