SpringBoot 实现视频分段播放(通过进度条来加载视频)

需求:现在我本地电脑中有一个文件夹,文件夹中都是视频,需要实现视频播放的功能。

问题:如果通过类似 SpringBoot static 文件夹的方式来实现,客户端要下载好完整的视频之后才可以播放,并且服务端也会占用大量宽带。所以这里考虑采取视频分段的方式进行下载,客户端播放视频时,可以通过进度条调节视频进度。

实现方法:在 SpringBoot 中支持自定义资源请求处理器,通过自定义的资源处理器来实现。

依赖:主要就是 SpringBoot 的相关依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

编写一个自定义资源请求处理器,需要继承 ResourceHttpRequestHandler 重写 getResource() 方法。该自定义处理器还需要加上 @Component 注解。

在案例中 getResource() 方法中,需要拿到对应的视频地址,通过 Controller 层的代码通过 request.setAttribute("video-uri", videoUri) 设置 video-uri 的 value,value 可以是视频的本地路径,也可以是视频的唯一标识,需要按照自己的业务来传值。

import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;

import javax.servlet.http.HttpServletRequest;

/**
 * @author 17279
 */
@Component
public class VideoResourceHttpRequestHandler extends ResourceHttpRequestHandler {
  // 只需要重写 getResource 方法
  @Override
  protected Resource getResource(HttpServletRequest request) {
    // 这里的 videoUri 是在 Controller 中通过 request.setAttribute("video-uri", videoUri) 进来的值
    String videoUri = (String) request.getAttribute("video-uri"); // D:\Downloads\test.mp4
    // 可以通过 videoUri 传递的值根据我们的业务查找对应的文件
    return new FileSystemResource(videoUri);
  }
}

编写 Controller 层代码:

这里通过 request.setAttribute("video-uri", videoUri) 添加 video-uri 的 value,自定义处理中通过这个 value 找到向前端返回的视频。

import org.springframework.beans.factory.annotation.Autowired;
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.resource.ResourceHttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @author 17279
 */

@RestController
@RequestMapping("video")
public class VideoController {
  @Autowired
  private ResourceHttpRequestHandler resourceHttpRequestHandler;

  /**
    * @param fileName fileName 前端传递过来的视频文件名名称
    */
  @GetMapping(value = "/{fileName}")
  public void video(@PathVariable("fileName") String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    // 视频文件根目录【换成实际的视频根目录】
    final String videoBasePath = "D:/Downloads/";
    
    // 视频根目录 + 文件名称,找到对应的文件
    String videoUri = videoBasePath + fileName;
    Path videoPath = Paths.get(videoUri);

    if (Files.exists(videoPath)) {
      // 如果找到视频,那么返回视频信息
      String contentType = Files.probeContentType(videoPath);
      if (contentType != null && !"".equals(contentType)) {
        response.setContentType(contentType);
      }
      // video-path 主要是将视频的地址传递给自定义的资源处理器处使用
      request.setAttribute("video-uri", videoUri);
      resourceHttpRequestHandler.handleRequest(request, response);
    } else {
      // 如果文件不存在,那么跳到 404 页面
      response.setStatus(HttpServletResponse.SC_NOT_FOUND);
      response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
    }
  }
}

访问地址:http://localhost/video/test.mp4

访问效果:这里设置的视频跟目录是 D:/Downloads/,前端传递的 fileName 为 test.mp4,所以实际返回前端的文件为 D:/Downloads/test.mp4

在这里插入图片描述

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-09 23:34:04       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-09 23:34:04       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-09 23:34:04       57 阅读
  4. Python语言-面向对象

    2024-07-09 23:34:04       68 阅读

热门阅读

  1. react v18——env环境变量配置、打包配置(craco)

    2024-07-09 23:34:04       25 阅读
  2. Consul与CoreDNS的对比

    2024-07-09 23:34:04       22 阅读
  3. git 合并多次commit,提交MR

    2024-07-09 23:34:04       18 阅读
  4. Redis中测试Stream的例子

    2024-07-09 23:34:04       21 阅读
  5. 「AIGC」大数据开发语言Scala入门

    2024-07-09 23:34:04       24 阅读
  6. 易保全推动区块链应用与AI融合创新发展

    2024-07-09 23:34:04       22 阅读
  7. 如何在LabVIEW中使用FPGA模块

    2024-07-09 23:34:04       18 阅读
  8. 【FFMPEG基础(一)】解码源码

    2024-07-09 23:34:04       19 阅读
  9. Oracle的RECYCLEBIN回收站:轻松恢复误删对象

    2024-07-09 23:34:04       22 阅读
  10. 0703_ARM7

    0703_ARM7

    2024-07-09 23:34:04      21 阅读
  11. CI脚本的python基础

    2024-07-09 23:34:04       22 阅读
  12. uni-app + vue3项目引入unocss

    2024-07-09 23:34:04       18 阅读
  13. 深度学习 - 模型的保存与部署方式汇总

    2024-07-09 23:34:04       16 阅读