博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PHP + NGINX 控制视频文件播放,并防止文件下载
阅读量:6352 次
发布时间:2019-06-22

本文共 3221 字,大约阅读时间需要 10 分钟。

最简单的方法是使用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工具进行处理,把元数据放回文件头部即可。

转载于:https://www.cnblogs.com/lbnnbs/p/7384589.html

你可能感兴趣的文章
千万PV是什么意思?
查看>>
Amazon 推出 API 网关使用计划
查看>>
互联网流量超出路由器上限 或致全球断网
查看>>
《基于ArcGIS的Python编程秘笈(第2版)》——2.5 限制图层列表
查看>>
GNOME 地图 3.20 加入更多新特性 可用性得到加强
查看>>
《代码整洁之道:程序员的职业素养》导读
查看>>
《计算复杂性:现代方法》——习题
查看>>
Mozilla 释出更新修复中间人攻击漏洞
查看>>
思科表态反对网络中立
查看>>
《HTML5+CSS3网页设计入门必读》——1.5 利用多种Web浏览器执行测试
查看>>
Velocity官方指南-容器
查看>>
国家为何如此重视石墨烯?
查看>>
《Python和Pygame游戏开发指南》——1.14 配套网站上的更多信息
查看>>
Kafka+Flink 实现准实时异常检测系统
查看>>
利用mybatis查询两级树形菜单
查看>>
《慕客网:IOS基础入门之Foundation框架初体验》学习笔记 <一>
查看>>
Spring声明式事务管理之二:核心接口API
查看>>
LNMP环境安装(二)
查看>>
MFC对话框编程-图片控件
查看>>
nodejs启动webserver服务
查看>>