使用PHP逻辑流式传输文件

时间:2014-11-27 20:07:12

标签: php streaming

在我们的网站上,用户可以上传mp3音频和mp4视频媒体。他们还可以在其上设置私有/公共标志,以拒绝访问除他们之外的其他用户。

我们希望流式传输这些媒体并将它们与一些Javascript播放器一起显示,但由于我们需要执行一些PHP逻辑,因此我们不能让Web服务器对它们进行流式传输。

有什么方法可以流式传输这些媒体并在之前执行某些PHP逻辑(授予或拒绝访问权限)?

1 个答案:

答案 0 :(得分:0)

我已经为下载编写并测试了此脚本。应该也适合流媒体。     

$file_name = $_GET['file'];
/* define UPLOADS_DIR */
$file_path = UPLOADS_DIR . $file_name;

if (!is_file($file_path)) {
    header('HTTP/1.0 404 Not Found');
    exit;
}

/* define has_access */
if (!has_access($file_name)) {
    header('HTTP/1.0 403 Forbidden');
    exit;
}

$file = fopen($file_path, 'rb');

if (!$file) {
    header('HTTP/1.0 500 Internal Server Error');
    exit;
}

$file_size = filesize($file_path);

$start = 0;
$end = $file_size - 1;
$length = $file_size;

if (isset($_SERVER['HTTP_RANGE'])) {

    if (!preg_match('/^bytes=(\d*)-(\d*)/', $_SERVER['HTTP_RANGE'], $matches) || ($matches[1] === '' && $matches[2] === '')) {
        header('HTTP/1.1 416 Requested Range Not Satisfiable');
        fclose($file);
        exit;
    }

    $start = (int)$matches[1];
    $end = $matches[2] === '' ? $file_size - 1 : (int)$matches[2];

    if ($start >= $end || $end >= $file_size) {
        header('HTTP/1.1 416 Requested Range Not Satisfiable');
        fclose($file);
        exit;
    }

    $length = $end - $start + 1;
}

if ($length != $file_size) {
    header('HTTP/1.1 206 Partial Content');
    header('Content-Range: bytes ' . $start . '-' . $end . '/' . $file_size);
}
else {
    header('HTTP/1.1 200 OK');
}

header('Pragma: public');
header('Expires: -1');
header('Cache-Control: public, must-revalidate, post-check=0, pre-check=0');
header('Accept-Ranges: bytes');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $file_name . '"');
header('Content-Length: ' . $length);

set_time_limit(0);

/* you can modify the chunk size */
$chunk_size = 1024 * 8;

fseek($file, $start);
$left = $length;

while ($left > 0) {

    $size = $chunk_size > $left ? $left : $chunk_size;

    echo fread($file, $size);
    ob_flush();
    flush();

    if (connection_status()) {
        fclose($file);
        exit;
    }

    $left -= $size;
}

fclose($file);