今日学习
关注博主,每天分享实战技术和优秀资源推荐(有好资源可以推荐给博主)。
博主一直做开源产品,目前已开源多款后台架构,开源地址:
https://gitee.com/msxy
H5-Video视频播放
<video width="320" height="240" controls> <source src="movie.mp4" type="video/mp4"> <source src="movie.ogg" type="video/ogg"></video>
详细参数使用说明:
<video controls autoplay loop preload="auto" poster="img/popup-img.png" webkit-playsinline="true" playsinline="true" x5-video-player-type="h5" x5-video-player-fullscreen="true" x-webkit-airplay="allow" x5-video-orientation="portraint" style="object-fit:fill"> <source src="video.mp4" type="video/mp4"> <source src="video.ogg" type="video/ogg; codecs=dirac, speex"> <p>你的浏览器不支持 <code>video</code> 标签.</p></video>
如何防止视频连接被获取
正常模式下,在<source src=”movie.mp4″ type=”video/mp4″>中直接使用了视频的地址,比如:movie.mp4。这样通过查看源代码或者F12能很快的定位到视频的全路径地址,那么如何控制视频地址不对外展示呢?
前端编写似乎还,不要暴露mp4等视频地址,编写方式如下:
<source src="+prefix+/kclient/getVideo/+id+" type="video/mp4">
视频地址换成后台请求地址,请求后台根据传入的id查询出对应的视频信息,将视频信息通过response流的模式写出,代码如下:
@RequestMapping("/getVideo/{id}") public void getVideo(HttpServletRequest request,HttpServletResponse response,@PathVariable String id){ //视频资源存储信息 PageData pd = new PageData(); pd.put("id",id); PageData filePd = sourceService.findVideoInfo(pd); response.reset(); //获取从那个字节开始读取文件 String rangeString = request.getHeader("Range"); try { //获取响应的输出流 OutputStream outputStream = response.getOutputStream(); File file = new File(ParaUtil.localName+filePd.get("file_path").toString()); if(file.exists()){ RandomAccessFile targetFile = new RandomAccessFile(file, "r"); long fileLength = targetFile.length(); //播放 if(rangeString != null){ long range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-"))); //设置内容类型 response.setHeader("Content-Type", "video/mp4"); //设置此次相应返回的数据长度 response.setHeader("Content-Length", String.valueOf(fileLength - range)); //设置此次相应返回的数据范围 response.setHeader("Content-Range", "bytes "+range+"-"+(fileLength-1)+"/"+fileLength); //返回码需要为206,而不是200 response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); //设定文件读取开始位置(以字节为单位) targetFile.seek(range); }else {//下载 //设置响应头,把文件名字设置好 response.setHeader("Content-Disposition", "attachment; filename="+filePd.get("name")); //设置文件长度 response.setHeader("Content-Length", String.valueOf(fileLength)); //解决编码问题 response.setHeader("Content-Type","application/octet-stream"); } byte[] cache = new byte[1024 * 300]; int flag; while ((flag = targetFile.read(cache))!=-1){ outputStream.write(cache, 0, flag); } }else { String message = "file:"+filePd.get("name")+" not exists"; //解决编码问题 response.setHeader("Content-Type","application/json"); outputStream.write(message.getBytes(StandardCharsets.UTF_8)); } outputStream.flush(); outputStream.close(); } catch (FileNotFoundException e) { } catch (IOException e) { } }
视频意外流失,如何控制视频不被传播
在我们实际运营过程中,可能会存在视频被流失的风险,一旦视频流失可能会对企业造成很大的影响,那么如何避免视频被流出呢?
通过java对视频流进行加解密处理,及时视频外流,也无法对视频进行播放。
package com.qingfeng.util; import java.io.*; public class VideoEncodeUtil { public static void main(String[] args) throws Exception { encrypt("D:\\py交易\\11.mp4", "fuckyourself"); decrypt("D:\\py交易\\11.mp4", "D:\\py交易\\22.mp4", 4); System.out.println(readFileLastByte("D:\\py交易\\11.mp4", 12)); } /** * @title 文件file进行加密 * @description 文件file进行加密 * @author Administrator * @updateTime 2021/6/29 17:36 */ public static void encrypt(String fileUrl, String key) throws Exception { File file = new File(fileUrl); String path = file.getPath(); if (!file.exists()) { return; } int index = path.lastIndexOf("\\"); String destFile = path.substring(0, index) + "\\" + "abc"; File dest = new File(destFile); //获取待加密文件的输入流 InputStream in = new FileInputStream(fileUrl); //创建中转文件输出流 OutputStream out = new FileOutputStream(destFile); //待加密文件的流 byte[] buffer = new byte[1024]; int r; //加密之后的文件的流 byte[] buffer2 = new byte[1024]; while ((r = in.read(buffer)) > 0) { for (int i = 0; i < r; i++) { byte b = buffer[i]; //buffer2[i]=b==255?0:++b;//每个字节加2加密 b += 2; buffer2[i] = b; } out.write(buffer2, 0, r); out.flush(); } in.close(); out.close(); file.delete(); dest.renameTo(new File(fileUrl)); appendMethodA(fileUrl, key); System.out.println("加密成功"); } /** * @title appendMethodA * @description appendMethodA * @author Administrator * @updateTime 2021/6/29 17:42 */ public static void appendMethodA(String fileName, String content) { try { //打开一个随机访问文件流,按读写方式 RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw"); //文件长度,字节数 long fileLength = randomFile.length(); //将写文件指针移到文件尾。 randomFile.seek(fileLength); randomFile.writeBytes(content); randomFile.close(); } catch (IOException e) { e.printStackTrace(); } } /** * @title 解密 * @description 解密 * @author Administrator * @updateTime 2021/6/29 17:40 */ public static String decrypt(String fileUrl, String tempUrl, int keyLength) throws Exception { File file = new File(fileUrl); if (!file.exists()) { return null; } File dest = new File(tempUrl); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } //获取待解密的文件输入流 InputStream is = new FileInputStream(fileUrl); //创建目标文件输出流,用来生成解密后的文件 OutputStream out = new FileOutputStream(tempUrl); byte[] buffer = new byte[1024]; byte[] buffer2 = new byte[1024]; byte bMax = (byte) 255; long size = file.length() - keyLength; int mod = (int) (size % 1024); int div = (int) (size >> 10); int count = (mod == 0) ? div : (div + 1); int k = 1; int r; while (((k <= count) && ((r = is.read(buffer)) > 0))) { if ((mod != 0) && (k == count)) { r = mod; } for (int i = 0; i < r; i++) { byte b = buffer[i]; //buffer2[i]=b==0?bMax:--b;//每个字节减2解码 b -= 2; buffer2[i] = b; } out.write(buffer2, 0, r); k++; } out.close(); is.close(); return tempUrl; } /*** 判断文件是否加密 *@paramfileName *@return* * 加密成功返回key * 加密失败返回非key的字符串*/ public static String readFileLastByte(String fileName, int keyLength) { File file = new File(fileName); if (!file.exists()) { return "没有文件"; } StringBuffer str = new StringBuffer(); try { //打开一个随机访问文件流,按读写方式 RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw"); //文件长度,字节数 long fileLength = randomFile.length(); //将写文件指针移到文件尾。 for (int i = keyLength; i >= 1; i--) { randomFile.seek(fileLength - i); str.append((char) randomFile.read()); } randomFile.close(); return str.toString(); } catch (IOException e) { e.printStackTrace(); } return "异常"; }}
主题授权提示:请在后台主题设置-主题授权-激活主题的正版授权,授权购买:RiTheme官网
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。本站所有文章,如遇付费下载内容。需要付费之后获取提款吗之后网盘观看学习和下载,不会产生第二次费用。