轉子於: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>
