SpringMVC流式传输媒体数据的方法

 更新时间:2025年07月03日 08:59:27   作者:javadoge  
Spring Boot利用ResourceHttpRequestHandler实现媒体流传输,支持分片加载避免全量下载,需自定义继承该类,重写getResource方法,并配置ResponseEntity及异常处理,推荐使用MinIO或视频云点播优化性能,本文给大家介绍SpringMVC流式传输媒体数据的方法,感兴趣的朋友一起看看吧

借助Spring的ResourceHttpRequestHandler可以实现媒体数据的传输,比如在线播放视频、预览图片等。

目前已知Spring Boot传输视频流的方法

  • 读取整个视频文件,然后把文件流写入HttpServletResponse的OutputStream。
    (此方法可行,但是需要消耗较多的服务器资源,且客户端需要下载整个视频才能播放)
  • 使用HTTP的Range实现分片加载,但是需要手动实现,比较麻烦。
  • 使用Spring自带的ResourceHttpRequestHandler是最佳实践。

思路

ResourceHttpRequestHandler是Spring Boot用于加载静态资源的一个类,默认用于从"classpath:/static"等目录读取静态资源,以便前端访问。我们可以继承它自定义一个实现。

使用方法

在项目的config包(推荐)继承ResourceHttpRequestHandler并重写getResource方法,使其返回所需要呈现给前端的资源(org.springframework.core.io.Resource)

package com.example.server.config;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.util.List;
@Component
public class CustomResourceHttpRequestHandler extends ResourceHttpRequestHandler {
    private Resource resource;
    @Override
    protected Resource getResource(@NonNull HttpServletRequest request) {
        return this.resource;
    }
    public void setResource(Path filePath) throws MalformedURLException {
        this.resource = new UrlResource(filePath.toUri());
        setLocations(List.of(this.resource));
    }
}

控制层注入CustomResourceHttpRequestHandler,并向setResource方法传入文件路径(java.nio.file.Path),设置请求头,最后让customResourceHttpRequestHandler处理请求。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.file.Path;
import java.nio.file.Paths;
@Controller
@RequestMapping("/files")
public class FileController {
    @Autowired
    private CustomResourceHttpRequestHandler resourceHttpRequestHandler;
    @GetMapping("/{filename}")
    public ResponseEntity<?> getFile(@PathVariable String filename, HttpServletRequest request, HttpServletResponse response) {
        try {
            // 解析文件路径
            Path filePath = Paths.get("D:/StorageService").resolve(filename).normalize();
            // 检查文件是否存在
            if (!filePath.toFile().exists()) {
                return new ResponseEntity<>(HttpStatus.NOT_FOUND);
            }
            // 设置资源路径
            resourceHttpRequestHandler.setResource(filePath);
            // 设置响应头,inline 会在浏览器中显示或播放文件
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"");
            // 让 CustomResourceHttpRequestHandler 处理请求
            resourceHttpRequestHandler.handleRequest(request, response);
            return new ResponseEntity<>(HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

注意点

控制层返回值需要ResponseEntity类型(org.springframework.http.ResponseEntity),且try-catch不能省略,否则可能会不断抛出异常(AsyncRequestNotUsableException和IOException)但不影响正常使用。

其他方案

如果有条件也可以使用MinIO,或者视频云点播VOD。他们提供了现成的解决方案,通过调用API可以获取视频等文件的直链。

参考资料

springboot+vue播放视频流(无需下载视频,可以拖动进度、倍速播放)

到此这篇关于java的文章就介绍到这了,更多相关java内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringMVC 限流的示例代码

    SpringMVC 限流的示例代码

    这篇文章主要介绍了SpringMVC 限流的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • 详解Java内存泄露的示例代码

    详解Java内存泄露的示例代码

    这篇文章通过一个Demo来简要介绍下ThreadLocal和ClassLoader导致内存泄露最终OutOfMemory的场景。下面通过示例代码给大家分享Java内存泄露的相关知识,感兴趣的朋友一起看看吧
    2017-12-12
  • java 线程池的实现方法

    java 线程池的实现方法

    在本篇文章里小编给大家整理了关于java 线程池的实现方法,有兴趣的朋友们可以学习参考下。
    2020-02-02
  • Java的jstack命令使用示例详解

    Java的jstack命令使用示例详解

    jstack 命令非常的简单,我们可以通过 jstack -h 或者 jstack -help 命令查看它的用法详情,今天通过本文重点给大家介绍Java的jstack命令使用,感兴趣的朋友一起看看吧
    2022-03-03
  • Java利用SpEL表达式实现权限校验

    Java利用SpEL表达式实现权限校验

    这篇文章主要为大家详细介绍了Java如何利用SpEL表达式实现权限校验功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-01-01
  • SpringBoot集成FastDFS实现防盗链功能

    SpringBoot集成FastDFS实现防盗链功能

    FastDFS是一个高性能的分布式⽂件系统,本文将为大家详细介绍一下SpringBoot如何集成FastDFS实现防盗链功能,感兴趣的小伙伴可以跟随小编一起学习一下
    2025-04-04
  • java中字符进行全角半角转换示例代码

    java中字符进行全角半角转换示例代码

    全角:指一个字符占用两个标准字符位置,而半角:指一字符占用一个标准的字符位置,在日常开发中经常会遇到全角半角转换的要求,下面这篇文章主要给大家介绍了关于java中字符进行全角半角转换的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-08-08
  • 一文详解如何使用Spring MVC实现RESTful API接口

    一文详解如何使用Spring MVC实现RESTful API接口

    本文主要介绍了如何使用SpringMVC实现RESTful API,包括RESTful的核心概念、设计原则、传参方式比较、SpringMVC实现示例及关键注解说明,还介绍了API测试工具和SpringMVC的匹配机制,强调了在实际开发中保持RESTful风格的一致性和合理设计资源路径的重要性
    2025-10-10
  • 6种SpringBoot解决跨域请求的方法整理

    6种SpringBoot解决跨域请求的方法整理

    跨域资源共享是一种标准机制,允许服务器声明哪些源可以访问其资源,在SpringBoot应用中,有多种方式可以解决跨域问题,本文主要介绍了6种常见的解决方案,大家可以根据需求自行选择
    2025-04-04
  • Java实现SHA-256加密算法的完全解析

    Java实现SHA-256加密算法的完全解析

    SHA-256是一种散列(哈希)算法,用于将任意长度的数据映射为固定长度的散列值,以保证数据完整性。本文将为大家介绍一下SHA-256加密算法的原理与实现,希望对大家有所帮助
    2023-02-02

最新评论