视频传输到浏览器


/**
 * 上传视频。http://localhost:8080/Video/upload
 */
@RequestMapping("/upload")
@ResponseBody
public R uploadPhoto(MultipartFile file) {
    if (file == null) {
        return R.error("请选择视频上传");
    }

    String fileName = file.getOriginalFilename();//获取初始文件名
    int indexOf = fileName.lastIndexOf(".");
    if(indexOf == -1){
        return R.error("视频格式不正确");
    }
    String suffix = fileName.substring(indexOf);//得到文件名后缀 .mp4

    if(suffix==null||suffix.equals(".")){
        return R.error("视频格式不正确");
    }
    //.mp4
    if(!(suffix.equals(".mp4"))){
        return R.error("视频格式不正确");
    }

    // 生成随机文件名
    String name = UUID.randomUUID().toString().replaceAll("-", "") + suffix;

    //获取当前项目下视频保存的路径
    String uploadPath = null;
    try {
        //   c:\\a2295929271\ .....
        uploadPath = new File("").getCanonicalPath();
    } catch (IOException e) {
        throw new RuntimeException("获取项目路径失败", e);
    }

    // 确定文件存放的路径
    String ans = uploadPath + File.separator + "file" + File.separator + "video" + File.separator + name;

    File dest = new File(ans);
    try {
        // 存储文件
        file.transferTo(dest);
    } catch (IOException e) {
        throw new RuntimeException("上传文件失败,服务器发生异常!", e);
    }

    String result = domain + name;


    return R.ok().put("url",result);
}

确实,视频传输上去了,一百多M的视频,没什么问题。。。。不知道传到服务器上有没有问题,估计应该有。

 

然而把视频读取到浏览器上:

/**
 * 获取视频。
 * http://localhost:8080/Video/load/626905be16ce4f36b033693cd61662dc.mp4
 * 得到项目路径下 /file/video/48c3df11ca5f4c80bab198159e41a5de.png的图片
 */
@RequestMapping("/load/{name}")
@ResponseBody
public void loadPhoto(HttpServletResponse response,@PathVariable("name") String name) {
    String videoPath = null;
    FileInputStream fis = null;
    OutputStream os = null ;
    try {
        //得到项目中视频保存的路径
        videoPath = new File("").getCanonicalPath() + File.separator + "file" + File.separator + "video";
    } catch (IOException e) {
        throw new RuntimeException("获取项目路径失败", e);
    }
    videoPath += File.separator + name;

    try {
        fis = new FileInputStream(videoPath);
        int size = fis.available(); // 得到文件大小
        byte data[] = new byte[size];
        fis.read(data); // 读数据
        fis.close();

        response.setContentType("video/mp4"); // 设置返回的文件类型
        os = response.getOutputStream();
        os.write(data);

        os.flush();
        os.close();
        os = null;fis = null;
    } catch (FileNotFoundException e) {
        throw new RuntimeException("........文件" +videoPath + "未找到......", e);
    } catch (IOException e) {
        throw new RuntimeException("..文件大小读取异常..", e);
    }
}

 出现异常了,。。。百度说也就 是 文件过大了。

这样,百度到了一个方法:分片循环输出。

修改代码:

/**
 * 获取视频。
 * http://localhost:8080/Video/load/626905be16ce4f36b033693cd61662dc.mp4
 * 得到项目路径下 /file/video/48c3df11ca5f4c80bab198159e41a5de.png的图片
 */
@RequestMapping("/load/{name}")
@ResponseBody
public void loadPhoto(HttpServletResponse response,@PathVariable("name") String name) {
    String videoPath = null;
    FileInputStream fis = null;
    OutputStream os = null ;
    response.setContentType("video/mp4");

    try {
        //得到项目中视频保存的路径
        videoPath = new File("").getCanonicalPath() + File.separator + "file" + File.separator + "video";
    } catch (IOException e) {
        throw new RuntimeException("获取项目路径失败", e);
    }
    videoPath += File.separator + name;

    try {
        fis = new FileInputStream(videoPath);
        int size = fis.available(); // 得到文件大小
        os = response.getOutputStream();//得到输出流
        byte[] data = new byte[1024 * 1024 * 5];// 5MB

        // 5M 大小循环写出
        fis.read(data); // 读数据
        int len = 0;
        while ((len = fis.read(data)) != -1) {
            System.out.println("111111111111111");
            os.write(data,0,len);
        }


        os.flush();
        os.close();
        fis.close();
        os = null;
        fis = null;
    } catch (FileNotFoundException e) {
        throw new RuntimeException("........文件" +videoPath + "未找到......", e);
    } catch (IOException e) {
        throw new RuntimeException("文件操作出现异常,请联系管理员", e);
    }
}

 仍然存在刚才的问题。。。。。。

待解决

 

过了两天继续写博客,问题已解决。不能一次性传递全部视频,要分段的传递

在每次的请求的头中加入 Range:bytes=xx-yy        xx yy就是字节开始和结束点。

重新写了个接口:


/**
 * 获取视频流
 * @param response
 * @param fileName 视频存放信息索引
 * @return
 * @author xWang
 * @Date 2020-05-20
 */
@RequestMapping("/getVideo/{fileName}")
public void getVideo(HttpServletRequest request, HttpServletResponse response,@PathVariable("fileName") String fileName) {
    //获取视频路径
    String videoPath = null;
    try {
        //得到项目中视频保存的路径
        videoPath = new File("").getCanonicalPath() + File.separator + "file" + File.separator + "video";
    } catch (IOException e) {
        throw new RuntimeException("获取项目路径失败", e);
    }
    videoPath += File.separator + fileName;


    //视频资源存储信息
    response.reset();
    //获取从那个字节开始读取文件
    String rangeString = request.getHeader("Range");
    try {
        //获取响应的输出流
        OutputStream outputStream = response.getOutputStream();
        File file = new File(videoPath);
        if(file.exists()){
            RandomAccessFile targetFile = new RandomAccessFile(file, "r");
            long fileLength = targetFile.length();
            //播放
            if(rangeString != null){

                long range = Long.parseLong(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
                //设置内容类型
                response.setHeader("Content-Type", "video/mov");
                //设置此次相应返回的数据长度
                response.setHeader("Content-Length", String.valueOf(fileLength - range));
                //设置此次相应返回的数据范围
                response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength);
                //返回码需要为206,而不是200
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                //设定文件读取开始位置(以字节为单位)
                targetFile.seek(range);
            }else {//下载

                //设置响应头,把文件名字设置好
                response.setHeader("Content-Disposition", "attachment; filename="+fileName );
                //设置文件长度
                response.setHeader("Content-Length", String.valueOf(fileLength));
                //解决编码问题
                response.setHeader("Content-Type","application/octet-stream");
            }


            byte[] cache = new byte[1024 * 300];
            int flag;
            while ((flag = targetFile.read(cache))!=-1){
                outputStream.write(cache, 0, flag);
            }
        }else {
            String message = "file:"+fileName+" not exists";
            //解决编码问题
            response.setHeader("Content-Type","application/json");
            outputStream.write(message.getBytes(StandardCharsets.UTF_8));
        }

        outputStream.flush();
        outputStream.close();

    } catch (FileNotFoundException e) {

    } catch (IOException e) {

    }
}

 

 

 问题已解决。而且在安卓端访问的时候,也可以很好的变成访问在线播放的效果,给用户很好的体验。

    

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM