PHP + NGINX 控制视频文件播放,并防止文件下载
最简单的方法是使用NGINX的 internal 功能
server {
listen 80;
server_name www.xxx.com;
location / {
index index.php index.html index.htm;
root /xxx;
if (!-e $request_filename) {
rewrite ^/index.php(.*)$ /index.php?s=$1 last;
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
# 这里使用internal做下载防护,只允许内部程序(PHP等)访问,这样外部直接访问这个地址就会提示404错误
location ~ \.mp4$ {
internal;
# 这里的路径配置是可选的,可以配置到网站外部,和其他location里的配置路径是一个意思,可以更好的防止文件被通过网址下载
root /bbb;
}
location ~ \.php$ {
root /xxx;
try_files $uri =404;
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
然后在PHP中通过header('Location: /xxx/aa.mp4')访问,但这个只适合于小文件,因为这种方式不支持Content-Range和HTTP 206,导致不支持断点续传和视频文件的边下边播
最好的方式是通过header('X-Accel-Redirect: /xxx/aa.mp4')访问,X-Accel-Redirect支持Content-Range和HTTP 206,Apache里面是X-Sendfile
如果不能配置nginx的internal选项,或者nginx不支持X-Accel-Redirect,却要使用断点续传、边下边播和下载防护,那么就要通过PHP代码来控制
思路上是使用token鉴权,首先下载文件前由前端请求一个token,这个token由用户ID+时间戳+视频ID组成,然后存储到session并加密后发送给前端
$token = $_SESSION['uid'] . '|' . time() . '|' . $id;
// 保存未加密token到seesion
$_SESSION['video_token'] = $token;
// 加密token以便发送到客户端
$token = Mcrypt::encode($token, 'lbnnbs');
前端收到token,向下载控制器网址发送token请求文件下载,控制器对token解码,判断Session是否一致、用户ID是否正确、是否超时、视频ID是否正确
然后将视频ID转换为文件地址,通过PHP读取文件发送给前端下载。并通过发送Content-Range和HTTP 206来支持断点续传、边下边播等操作
$id = decodeIdFromToken($token); $file = getFilePath($id); SendVideo($file);
private function SendVideo($file) {
header("Content-type: video/mp4");
header("Accept-Ranges: bytes"); $size = filesize($file);
if (isset($_SERVER['HTTP_RANGE'])) {
header("HTTP/1.1 206 Partial Content");
list($name, $range) = explode("=", $_SERVER['HTTP_RANGE']);
list($begin, $end) = explode("-", $range);
if ($end == 0)
$end = $size - 1;
}else {
$begin = 0;
$end = $size - 1;
}
header("Content-Length: " . ($end - $begin + 1));
header("Content-Disposition: filename=" . basename($file));
header("Content-Range: bytes " . $begin . "-" . $end . "/" . $size); $fp = fopen($file, 'rb');
fseek($fp, $begin);
while (!feof($fp)) {
$p = min(1024, $end - $begin + 1);
$begin += $p;
echo fread($fp, $p);
}
fclose($fp);
} private function decodeIdFromToken($token) {
if (empty($_SESSION['uid'])) {
return false;
} $token = Mcrypt::decode($token, 'lbnnbs'); if ($token != $_SESSION['video_token']) {
//token解密失败,判定失效
return false;
} $token_arr = explode('|', $token); if (intval($token_arr[0]) != $_SESSION['uid']) {
// token不是当前用户,判定失效
return false;
} if (intval($token_arr[1]) < time() - 10) {
// token生成于10秒前,判定失效
return false;
} unset($_SESSION['video_token']); return $token_arr[2]; // 返回id
}
另外需要注意的是,很多时候mp4文件会无法支持边下边播,这是因为在转码或者压缩视频文件到mp4的时候把文件的元数据移除了或者放到了文件的末尾,导致前端播放器不能第一时间获取到视频文件的播放时长等信息,只能全部下载完毕后或者直到读取到了元数据后才能播放。这个时候可以使用qt-faststart.exe工具进行处理,把元数据放回文件头部即可。
PHP + NGINX 控制视频文件播放,并防止文件下载的更多相关文章
- 网站上flv,MP4等格式的视频文件播放不出来的解决办法
在做一个网站时,发现视频文件,比如flv,MP4格式在本地可以正常的播放,但是传到了开发机器上,就不行了.播放器的文件地址是对的,就是一直没有反应. 经过长时间的实验,发现问题在与iis的设置问题.i ...
- Emgu 学习(2) 视频文件播放
播放AVI视频文件 static void Main(string[] args) { CvInvoke.NamedWindow("TestVideo", NamedWindowT ...
- JS控制视频的播放
在用js定时器控制视频时, html部分: <video id="video_1"> <source id="source_1" src=&q ...
- C#获取视频文件播放长度
下面两种方法只支持部分视频格式,一般格式mp3,wma等等支持 1.使用Shell32 添加引用,选择COM中的Microsoft Shell Controls And Automation引用 // ...
- Video组件:控制视频的播放与暂停
来自<sencha touch权威指南>第10章,315页开始 app.js代码如下: Ext.require(['Ext.Video','Ext.MessageBox','Ext.Too ...
- H5网页播放器播不了服务器上的mp4视频文件
打开IIS,在功能视图里找到MIME类型菜单,打开该菜单后鼠标右键添加.mp4扩展名的MIME类型video/mp4 其他视频文件播放不了估计也得在IIS里添加对应的MIME类型(从服务器下载文件时也 ...
- C# WPF 用MediaElement控件实现视频循环播放
在WPF里用MediaElement控件,实现一个循环播放单一视频的程序,同时可以控制视频的播放.暂停.停止. 一种方式,使用MediaElement.MediaEnded事件,在视频播放结束后,自动 ...
- Unity中带有alpha通道的视频叠加播放
问题: 如何让两个透明视频叠加播放 解决播放: 1:使用Unity自带的shader,shader代码如下所示 Shader "Unlit/MaskVideo" { Propert ...
- 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步
深入理解MVC MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...
随机推荐
- gerrit配置和使用
参考http://www.cnblogs.com/tesky0125/p/5973642.html 1.安装gerrit replication插件 mkdir ~/tmp cp gerrit-2.1 ...
- 微信小程序客服消息使用
客服消息使用 为丰富小程序的服务能力,提高服务质量,微信为小程序提供客服消息能力,以便小程序用户可以方便快捷地与小程序服务提供方进行沟通. xiaokefu.com.cn 功能介绍 用户可使用小程序客 ...
- 微服务之分布式跟踪系统(springboot+zipkin+mysql)
通过上一节<微服务之分布式跟踪系统(springboot+zipkin)>我们简单熟悉了zipkin的使用,但是收集的数据都保存在内存中重启后数据丢失,不过zipkin的Storage除了 ...
- Java性能调优:利用JMC分析性能
Java性能调优作为大型分布式系统提供高性能服务的必修课,其重要性不言而喻. 好的分析工具能起到事半功倍的效果,利用分析利器JMC.JFR,可以实现性能问题的准确定位. 本文主要阐述如何利用JMC分析 ...
- Java-Runoob-高级教程-实例-时间处理:01. Java 实例 - 格式化时间(SimpleDateFormat)
ylbtech-Java-Runoob-高级教程-实例-时间处理:01. Java 实例 - 格式化时间(SimpleDateFormat) 1.返回顶部 1. Java 实例 - 格式化时间(Sim ...
- H5移动端开发vue+vux
项目src中用到的npm包有(从编译打包到最终部署仍不能移除)1:vue 渐进式 JavaScript 框架 http://cn.vuejs.org/v2/guide/2: ...
- String MVC @RequestParam(required=false) int XXX 参数为空报错解决方法
今天在用@RequestParam(required=false) int XXX 取参数的时候,当参数没有的时候Spring默认赋值为空.而此时使用基本类型int,所以报错,建议使用包装类 Inte ...
- [UE4]模拟物理子弹
模拟物理子弹有时候会穿透对象,所以不建议使用
- Unicode String to a UTF-8 TypedArray Buffer in JavaScript
https://coolaj86.com/articles/unicode-string-to-a-utf-8-typed-array-buffer-in-javascript/
- CRM 总是弹出登录窗口
最近测试机总是会出现登录窗口,也能正常进入系统,但是会反复出现. 环境:CRM2016 问题:总是弹出登录窗口 解决方法: