視頻傳輸到瀏覽器


/**
 * 上傳視頻。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