PHP + NGINX 控制視頻檔案播放,並防止檔案下載

來源:互聯網
上載者:User

標籤:begin   location   資料   oca   style   encode   邊下邊播   返回   發送   

最簡單的方法是使用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 控制視頻檔案播放,並防止檔案下載

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.