前言
对于一些视频/ 音频/ 图片 等资源文件 为了不被比别人私有利用我们一般会对这些 资源进行加密或者特殊处理 比如 防盗链 或者隐藏资源真实地址 这里其中有一种比较常用有效的加密方式利用BLOB加密。
一丶BOLB是什么?
BOLB(binary large object),二进制大对象,是一个可以存储二进制文件的容器。
原理:
1.我们将获取到的视频资源 转换成BLOB类型的对象
2.通过URL.createObjectURL()给对象创建一个临时的由BLOB开头的URL
3.将创建的临时URL对象 放到引用资源的对象上
二丶案例
1.准备一个视频文件
2.后端写一个接口获取视频资源
@GetMapping("getVideo")
public void getVideo(HttpServletRequest request, HttpServletResponse response) throws Exception {
/*
* 在这里可以进行权限验证等操作
*/
//ResourceLoader的getResource获取项目中的资源
//Resource resource = resourceLoader.getResource("classpath:video/zhangpf.mp4");
ClassPathResource classPathResource = new ClassPathResource("video/zhangpf.mp4");
File f = classPathResource.getFile();
//File f = resource.getFile();
//获取文件名称
String fileName = f.getName();
//导出文件
String agent = request.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);
response.reset();
//由于火狐和其他浏览器显示名称的方式不相同,需要进行不同的编码处理
if (agent.indexOf("FIREFOX") != -1) {//火狐浏览器
response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("GB2312"), "ISO-8859-1"));
} else {//其他浏览器
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
}
//设置response编码
response.setCharacterEncoding("UTF-8");
response.addHeader("Content-Length", "" + f.length());
//设置输出文件类型 视频为:video/mp4 这里给个图片格式为混淆视听
response.setContentType("image/gif");
//获取response输出流
os = response.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());
}
}
}
}
}
3.准备一个前端页面用于获取视频资源。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!--zhangpf.cn-->
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="shortcut icon" href="#" />
</head>
<body>
<video id="app" controls="controls">
your browser does not support the video tag
</video>
<script type="text/javascript">
var elementById = document.getElementById("app");
var xmlHttpRequest = new XMLHttpRequest;
xmlHttpRequest.open("GET","getVideo",true);
xmlHttpRequest.responseType = 'blob';
//xmlHttpRequest.onload:只有 4 状态会触发
xmlHttpRequest.onreadystatechange = function() {
if (xmlHttpRequest.readyState==4 && xmlHttpRequest.status == 200) {//请求成功
//获取blob对象
var blob = xmlHttpRequest.response;
//获取blob对象地址,并把值赋给容器
var urlObj = URL.createObjectURL(blob);
elementById.setAttribute("src", urlObj);
}
};
xmlHttpRequest.send();
</script>
</body>
</html>
就此就初略简单完成 了。
实现思路
首先 如果需要加密,那肯定不能直接去链接服务器 上的视频地址,这样会暴露很多信息 先不说视频容易被窃取 就连一些服务器信息都会暴露,所以肯定要在后端 通过流的方式获取 ,获取到了流 那要 怎么转换就方便多了。
然后 获取到了流之后肯定要往前端传递信息,前端接收的时候设置接收类型为BLOB当然这个BLOB对象 也有对于的对象类型 比如我们是视频文件 那么在后端处理的时候我们就要设置ContentType为video/mp4,这样前端接收的 BLOB的默认类型就是视频 文件了 。
再然后 但如果这样的话 依然有可能通过点进去加密的链接中下载我们的视频,这样 的话我们的加密就 没有 很大的 意义了,原来的链接是加密的当时别人依然可以盗用我们的视频,所以这里耍一个小聪明,在后端传递给前端资源的时候我们可以将输出类型ContentType设置成image/gif图片资源类型 或者其它文本类型。
最后 当URL.CreateObjectURL()的时候因为传递过来的资源是完整的所以渲染到浏览器也是没有问题的 但是如果通过F12调试界面点到BLOB加密的 链接上就会以图片的形式展示,格式不对自然就没有展示我们的视频资源咯,就这样变相的保护了我们的视频资源。