Mp4视频播放接口Demo

如果直接返回文件流,前端使用video标签播放,则会出现视频无法拖动的问题。

1、demo controller层接口

package com.study.controller;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Locale;

/**
 * 视频播放接口
 *
 * @Author YL
 * @Create 2022/7/27 23:11
 * @Version 1.0
 */
@Controller
@RequestMapping("/video")
public class VideoController {

    private static final File mp4File = new File("G:\\迅雷下载\\111111.mp4");

    /**
     * 视频播放接口
     * http://localhost:8080/study/video/playVideo
     *
     * @return
     */
    @GetMapping(value = "/playVideo")
    @ResponseBody
    public void playVideo(HttpServletRequest request, HttpServletResponse response) throws Exception {
        ServletOutputStream outputStream = response.getOutputStream();
        RandomAccessFile targetFile = new RandomAccessFile(mp4File, "r");

        Long offset = 0L; // 偏移量
        Long returnLength = mp4File.length(); // 最终返回的数据量大小

        String rangeHeader = request.getHeader(HttpHeaders.RANGE); // 格式:Range: bytes=start-end
        if (StringUtils.isNotBlank(rangeHeader)) {
            // 分段返回从新计算偏移量和数据大小
            offset = Long.valueOf(rangeHeader.substring(rangeHeader.indexOf("=") + 1, rangeHeader.indexOf("-")));
            returnLength = mp4File.length() - offset;
            String end = rangeHeader.substring(rangeHeader.indexOf("-") + 1);
            if (StringUtils.isNotBlank(end)) {
                returnLength = Long.valueOf(end) - offset + 1;
            }

            // 设置响应头
            long endIndex = (offset + returnLength - 1) > mp4File.length() ? mp4File.length() : (offset + returnLength - 1);
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); // 断点续传设置206状态码
            response.setContentType("video/mp4");
            response.setHeader(HttpHeaders.CONTENT_RANGE, String.format(Locale.ROOT, "bytes %d-%d/%d", offset, endIndex, mp4File.length()));
            response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
            response.setHeader(HttpHeaders.CONTENT_LENGTH, returnLength + "");
        } else {
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + mp4File.getName());
            response.setHeader("Content-Length", String.valueOf(mp4File.length())); //设置文件长度
            response.setHeader("Content-Type", "application/octet-stream");
        }

        targetFile.seek(offset); //设定文件读取开始位置(以字节为单位)

        // 根据范围获取文件
        byte[] cache = new byte[1024 * 1024 * 10];
        int length;
        long countByte = 0L;
        boolean isBreak = false;
        while (!isBreak && (length = targetFile.read(cache)) != -1) {
            countByte += length;
            if (countByte > returnLength) {
                length = (int) (length - (countByte - returnLength));
                isBreak = true;
                cache = Arrays.copyOfRange(cache, 0, length);
            }
            outputStream.write(cache, 0, length);
        }
    }
}

2、前端使用video标签播放页面

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Titletitle>
head>
<body>
<video src="http://localhost:8080/study/video/playVideo" controls="controls" preload="metadata" width="800px" height="500px">video>
body>
html>

3、项目目录结构

Mp4视频播放接口Demo_第1张图片

4、测试

访问http://localhost:8080/study/video.html页面
Mp4视频播放接口Demo_第2张图片

你可能感兴趣的:(小功能实现,spring,boot)