Java网站视频资源加密
----------------------------------------------------------分享此文章,只为让版权能够得到更多的保护----------------------------------------------------------------------------
目前公司是做线上视频教育的,教育视频资源一直被盗取,版权被侵犯。领导特别重视此事,于是就开始探索如何加密。
果然,功夫不负有心人。。。。
为了遵守技术开源无私奉献的原则,让版权能够得到更多的保护,决定果断分享此功能的实现方法!
先带大家看一下主流视频网站的实现:
等等吧,就不过多展示了,目测很多网站都用这种加密方式,其中的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加密视频文件
所有内容皆为个人总结或转载别人的文章,只为学习技术。
若您觉得文章有用,欢迎点赞分享!
若无意对您的文章造成侵权,请您留言,博主看到后会及时处理,谢谢。