Java網站視訊資源加密
阿新 • • 發佈:2019-05-13
----------------------------------------------------------分享此文章,只為讓版權能夠得到更多的保護----------------------------------------------------------------------------
目前公司是做線上視訊教育的,教育視訊資源一直被盜取,版權被侵犯。領導特別重視此事,於是就開始探索如何加密。
果然,功夫不負有心人。。。。
為了遵守技術開源無私奉獻的原則,讓版權能夠得到更多的保護,決定果斷分享此功能的實現方法!
先帶大家看一下主流視訊網站的實現:
等等吧,就不過多展示了,目測很多網站都用這種加密方式,其中的src連結都是blob:http://xxx格式的,且根據連結無法獲取視訊源。因為這並不是一個線上的視訊存放地址,這樣你通過爬蟲指令碼也無法下載該視訊檔案
那麼具體如何實現的呢?
不急,咱們一步一步來:
第一步:java 伺服器介面,根據url 返回資源
package com.wf.course.web.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; @Controller public class VideoController { @ResponseBody @RequestMapping("/getVideoSrc") public OutputStream getVideoSrc(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse){ //1.建立檔案物件 File f = new File("D:/test/x.mp4"); //2.獲取檔名稱 String fileName = f.getName(); //3.匯出檔案 String agent = httpServletRequest.getHeader("User-Agent").toUpperCase(); InputStream fis = null; OutputStream os = null; try { //4.獲取輸入流 fis = new BufferedInputStream(new FileInputStream(f.getPath())); byte[] buffer; buffer = new byte[fis.available()]; fis.read(buffer); httpServletResponse.reset(); //5.由於火狐和其他瀏覽器顯示名稱的方式不相同,需要進行不同的編碼處理 if(agent.indexOf("FIREFOX") != -1){//火狐瀏覽器 httpServletResponse.addHeader("Content-Disposition", "attachment;filename="+ new String(fileName.getBytes("GB2312"),"ISO-8859-1")); }else{//其他瀏覽器 httpServletResponse.addHeader("Content-Disposition", "attachment;filename="+ URLEncoder.encode(fileName, "UTF-8")); } //6.設定response編碼 httpServletResponse.setCharacterEncoding("UTF-8"); httpServletResponse.addHeader("Content-Length", "" + f.length()); //設定輸出檔案型別 httpServletResponse.setContentType("video/mpeg4"); //7.獲取response輸出流 os = httpServletResponse.getOutputStream(); os.flush(); //8.輸出檔案 os.write(buffer); }catch(Exception e){ System.out.println(e.getMessage()); } finally{ //關閉流 try { if(fis != null){ fis.close(); } if(os != null){ os.flush(); } if(os != null){os.close(); } } catch (IOException e) { System.out.println(e.getMessage()); } } return os; } @RequestMapping("/getVideoBlob_V2") public OutputStream getVideoBlob_V2(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { String httpUrl = "https://wangfang.oss-cn-qingdao.aliyuncs.com/wf_video/videoPath/863E1B126B81B7B60993CC0B9B1EC1EA.mp3"; // 1.下載網路檔案 URL url = null; try { url = new URL(httpUrl); } catch (MalformedURLException e1) { e1.printStackTrace(); } InputStream inStream = null; OutputStream outputStream = null; try { //2.獲取連結 URLConnection conn = url.openConnection(); //3.輸入流 inStream = conn.getInputStream(); httpServletResponse.reset(); httpServletResponse.addHeader("Content-Disposition", "attachment;filename=" + httpUrl); //6.設定response編碼 httpServletResponse.setCharacterEncoding("UTF-8");//設定輸出檔案型別 httpServletResponse.setContentType("video/mpeg4"); //7.獲取response輸出流 outputStream = httpServletResponse.getOutputStream(); int byteRead; while ((byteRead = inStream.read()) != -1) { outputStream.write(byteRead); } } catch (IOException e) { e.printStackTrace(); System.out.println(e); } finally { try { inStream.close(); outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } return outputStream; } }
第二步:頁面新增<video>標籤引用
<video controls="controls" preload="auto" height="300" width="400" id="videoPath" type="video/mp4"> 您的瀏覽器不支援html5! </video>
第三步:頁面js處理,呼叫介面,載入資源
$(function () { var xhr = new XMLHttpRequest();//建立XMLHttpRequest物件 xhr.open('GET', 'http://localhost:8080/getVideoBlob_V2', true);//配置請求方式、請求地址以及是否同步 xhr.responseType = 'blob';//設定結果型別為blob; xhr.onload = function(e) { alert(this.status); if (this.status === 200) { // 獲取blob物件 var blob = this.response; console.log(blob); // 獲取blob物件地址,並把值賦給容器 $("#videoPath").attr("src", URL.createObjectURL(blob)); } }; xhr.send(); });
- 這裡使用的最原生的
XMLHttpRequest
物件語法,這裡最重要的一點是要設定responseType為blob,這樣接收到response直接就是一個blob物件供我們使用。這個responseType屬性不屬於http頭部資訊,而是ajax請求中XHR物件的屬性(預設為""也就是text
型別,而在一些封裝XHR的框架中,一般把預設值設為json
)。這樣就可以得到以blob:
開頭的臨時url地址,而且在向服務端請求時頁隱藏了真實的視訊地址。
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
。
參考文章及感謝其作者:通過BLOB加密視訊檔案
&n