轉子於:https://www.jianshu.com/p/04727924273d和https://blog.csdn.net/ffffffff8/article/details/87359640
前言:
現在許多視頻在線觀看網站,你如果打開chrome查看其video標簽,會發現它的src是一個以blob:
開頭的地址。比如下面這里是B站的截圖,可以看到他這里引入的並不是一個在線的視頻存放地址,這樣你通過爬蟲腳本也無法下載該視頻文件,通過一個new tab打開也於事無補,會提示你地址錯誤。
createObjectURL與BLOB
- 我們再回到那個以
blob:
開頭的神秘字符串,它其實是通過URL.createObjectURL
這個API生成的,該函數接收一個BLOB對象,返回該對象對應的DOMString
,這個字符串其實也可以看做是一個url地址,但它是與當前窗口的document
對象綁定的,也可以說是會話(session)級的,所以你在新的tab打開也就無效了 - 再來了解下BLOB,他的全稱為big binary large object,二進制大對象。如果把一個視頻文件轉換成二進制對象,其大小肯定很大,這樣理解就清楚多了。在瀏覽器端也提供了BLOB相關的API,通過
new Blog(...)
生成blog對象。 - 拿到blog對象后,再通過
URL.createObjectURL
生成臨時地址,賦值給video標簽的src屬性,這樣就可以了。但其實可以直接從服務端接收二進制對象,就是服務端把視頻文件轉換成二進制對象,通過接口給到前端,前端再生成dom string
。
Video 使用 blob 二進制流需要前后端同時支持。
Java 生成 Blob 二進制流
/* * 在這里可以進行權限驗證等操作 */ //創建文件對象 File f = new File("E:\\test.mp4"); //獲取文件名稱 String fileName = f.getName(); //導出文件 String agent = getRequest().getHeader("User-Agent").toUpperCase(); InputStream fis = null; OutputStream os = null; try { fis = new BufferedInputStream(new FileInputStream(f.getPath())); byte[] buffer; buffer = new byte[fis.available()]; fis.read(buffer); getResponse().reset(); //由於火狐和其他瀏覽器顯示名稱的方式不相同,需要進行不同的編碼處理 if(agent.indexOf("FIREFOX") != -1){//火狐瀏覽器 getResponse().addHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes("GB2312"),"ISO-8859-1")); }else{//其他瀏覽器 getResponse().addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8")); } //設置response編碼 getResponse().setCharacterEncoding("UTF-8"); getResponse().addHeader("Content-Length", "" + f.length()); //設置輸出文件類型 getResponse().setContentType("video/mpeg4"); //獲取response輸出流 os = getResponse().getOutputStream(); // 輸出文件 os.write(buffer); }catch(Exception e){ System.out.println(e.getMessage()); } finally{ //關閉流 try { if(fis != null){ fis.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } finally{ try { if(os != null){ os.flush(); } } catch (IOException e) { System.out.println(e.getMessage()); } finally{ try { if(os != null){ os.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } } } }
HTML5 Video 使用 Blob
//創建XMLHttpRequest對象 var xhr = new XMLHttpRequest(); //配置請求方式、請求地址以及是否同步 xhr.open('POST', './play', true); //設置請求結果類型為blob xhr.responseType = 'blob'; //請求成功回調函數 xhr.onload = function(e) { if (this.status == 200) {//請求成功 //獲取blob對象 var blob = this.response; //獲取blob對象地址,並把值賦給容器 $("#sound").attr("src", URL.createObjectURL(blob)); } }; xhr.send();
<video id="sound" width="200" controls="controls"></video>