解决浏览器使用 vue-video-player播放视频不能拖动或点击进度条到指定位置播放,拖动或点击进度条会立即反弹回起点播放

饶谦
2023-12-01

使用vue/cli版本号: 5.0.0

 使用vue版本号: 2.6.14

使用 vue-video-player 版本号: 5.0.2

解决浏览器使用 vue-video-player播放视频不能拖动或点击进度条到指定位置播放,拖动或点击进度条会立即反弹回起点播放的问题

当前端video的src不是直接使用视频文件的地址,而是通过后台下载接口返回文件流时,后台返回流因为没为response的header设置一些参数,会在部分浏览器出现问题,比如在谷歌浏览器无法拖动进度条,因为Chrome浏览器默认请求会在 Header 添加一个Range如下:服务器要做的就是响应这个Header,所以做了Range的判断,存在则做一些处理

后端关键代码:

 /*
            * 当前端video的src不是直接使用视频文件的地址,而是通过后台下载接口返回文件流时,
            * 后台返回流因为没为response的header设置一些参数,
            *会在部分浏览器出现问题,比如在谷歌浏览器无法拖动进度条
            * Chrome浏览器默认请求会在 Header 添加一个Range如下:服务器要做的就是响应这个Header,
            * 所以做了Range的判断存在则做一些处理*/
            String rangeString = request.getHeader("Range");
            if (rangeString != null && rangeString.trim().length() > 0 && !"null".equals(rangeString)) {
                long range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));

                response.setHeader("Content-Type", "video/mp4");

                response.setContentLength(Math.toIntExact(file.length()));//10000是视频文件的大小,上传文件时都会有这些参数的

                response.setHeader("Content-Range", String.valueOf(range + (file.length() - 1)));//拖动进度条时的断点,其中10000是上面的视频文件大小,改成你的就好

                response.setHeader("Accept-Ranges", "bytes");

            }

后端文件下载完整代码参考service层

/**
     * @Description: 文件下载:以流的方式
     * @Date: 2022/11/14
     */
    public static String downloadFile(String filePath, HttpServletRequest request, HttpServletResponse response) {
        logger.info("传入路径参数" + filePath);
        FileInputStream fis = null;
        BufferedInputStream bis = null;

        try {
            //设置文件路径
            File file = new File(filePath);
            //获取文件名
            String fileName = file.getName();
            //转码
            String encodeFileName = URLEncoder.encode(fileName, "utf-8");
            logger.info("文件名" + file.getName());

            /*
            * 当前端video的src不是直接使用视频文件的地址,而是通过后台下载接口返回文件流时,
            * 后台返回流因为没为response的header设置一些参数,
            *会在部分浏览器出现问题,比如在谷歌浏览器无法拖动进度条
            * Chrome浏览器默认请求会在 Header 添加一个Range如下:服务器要做的就是响应这个Header,
            * 所以做了Range的判断存在则做一些处理*/
            String rangeString = request.getHeader("Range");
            if (rangeString != null && rangeString.trim().length() > 0 && !"null".equals(rangeString)) {
                long range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));

                response.setHeader("Content-Type", "video/mp4");

                response.setContentLength(Math.toIntExact(file.length()));//10000是视频文件的大小,上传文件时都会有这些参数的

                response.setHeader("Content-Range", String.valueOf(range + (file.length() - 1)));//拖动进度条时的断点,其中10000是上面的视频文件大小,改成你的就好

                response.setHeader("Accept-Ranges", "bytes");

            }
            //告诉浏览器输出内容为流
            response.setContentType("application/octet-stream");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + encodeFileName);
            response.addHeader("Content-Length", "" + file.length());
            byte[] buffer = new byte[1024];
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            OutputStream os = response.getOutputStream();
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            os.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        logger.info("下载成功");
        return null;
    }

 简单点的方法,直接在controller层写,不用service层,比较不规范

/**
     * 文件下载接口   http://localhost:8080/file/{fileName}
     *
     * @param fileName
     */
    @GetMapping("/{fileName}")
    public void downLoad(@PathVariable String fileName, HttpServletRequest request, HttpServletResponse response) throws IOException {

        // 根据文件的唯一标识码获取文件
        File file = new File(uploadParentPath, fileName);

        /*
         * 方式一:
         * 当前端video的src不是直接使用视频文件的地址,而是通过后台下载接口返回文件流时,
         * 后台返回流因为没为response的header设置一些参数,
         *会在部分浏览器出现问题,比如在谷歌浏览器无法拖动进度条
         * Chrome浏览器默认请求会在 Header 添加一个Range如下:服务器要做的就是响应这个Header,
         * 所以做了Range的判断存在则做一些处理*/
        /*String rangeString = request.getHeader("Range");
        if (rangeString != null && rangeString.trim().length() > 0 && !"null".equals(rangeString)) {
            long range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));

            response.setHeader("Content-Type", "video/mp4");

            response.setContentLength(Math.toIntExact(file.length()));//10000是视频文件的大小,上传文件时都会有这些参数的

            response.setHeader("Content-Range", String.valueOf(range + (file.length() - 1)));//拖动进度条时的断点,其中10000是上面的视频文件大小,改成你的就好

            response.setHeader("Accept-Ranges", "bytes");

        }*/
            //方式二:
           //解决浏览器使用 vue-video-player播放视频不能拖动或点击进度条到指定位置放,
            //拖动或点击进度条会立即反弹回起点播放的问题,直接设置下面两行就行
        response.setHeader("Accept-Ranges", "bytes");
        response.setContentLength(Math.toIntExact(file.length()));

        // 设置输出流的格式,告诉浏览器输出内容为流
        response.setContentType("application/octet-stream");
        // 设置文件名
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));

        ServletOutputStream os = response.getOutputStream();
        // 读取文件的字节流
        os.write(FileUtil.readBytes(file));
        os.flush();
        os.close();

    }

以上解决方案同样可解决使用kkFileView进行文件视频预览不能拖动或点击进度条到指定位置播放,拖动或点击进度条会立即反弹回起点播放的问题,以下是使用kkFileView进行文件视频预览的前端代码

<!--表格开始-->
    <el-table :data="tableData" border stripe  ref="multipleTable">
      <el-table-column  align="center" label="文件预览" width="200">
        <template slot-scope="scope">
          <el-button type="primary" @click="preview(scope.row.url)">
            <i class="el-icon-view">预览</i>
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!--表格结束-->


methods:{

 /*预览图片文件图片视频*/
    preview(url){
      window.open('https://file.keking.cn/onlinePreview?url='
          + encodeURIComponent(window.btoa((url))))
    },

},

 类似资料: