最近用hdfs上传了一个2.8g的视频,发现用原始的read方式会把整个视频加载到内存,会非常慢。所以使用hdfs的web api里面的按文件偏移量加载的方式。

参考:https://mobiforge.com/design-development/content-delivery-mobile-devices

首先安装扩展

# https://github.com/xaviered/php-WebHDFS/blob/master/README.md#status-of-a-filedirectory
$ composer require simpleenergy/php-webhdfs
public function read_hdfs() {
        //获取文件名
        $filename = $this->request->param('filename');

        $hdfs = new \org\apache\hadoop\WebHDFS(
            '192.168.1.2',
            '50070',
            'root',
            '192.168.1.2',
            '50020',
            true
        );
        //获取文件总大小
        $file_status = json_decode($hdfs->getFileStatus($filename),TRUE);

        //读取少量字节检测文件mime
        $response_ext = $hdfs->open($filename, 0,100);

        //读取文件并返回文件mime
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        $ext = $finfo->buffer($response_ext);

        header( 'Content-Type:'.$ext);

        list($start,) = $this->rangeHeader($file_status['FileStatus']['length']);

        $length = 1024 * 1024;//1mb 每次加载

        while (1) {
            //$start 文件偏移量
            $response = $hdfs->open($filename, $start,$length);
            if (!$response) break;
            echo $response;
            ob_flush();
            flush();
            $start += $length;
        }
        exit();
    }
    //处理视频range头,可以快进倒退等等
    public function rangeHeader($size = 0) {

        $length = $size;           // Content length
        $start  = 0;               // Start byte
        $end    = $size - 1;       // End byte

        header("Accept-Ranges: 0-$length");

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

            $c_end   = $end;
            // Extract the range string
            list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
            // Make sure the client hasn't sent us a multibyte range
            if (strpos($range, ',') !== false) {

                // (?) Shoud this be issued here, or should the first
                // range be used? Or should the header be ignored and
                // we output the whole content?
                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $start-$end/$size");
                // (?) Echo some info to the client?
                exit;
            }
            // If the range starts with an '-' we start from the beginning
            // If not, we forward the file pointer
            // And make sure to get the end byte if spesified
            if ($range == '-') {

                // The n-number of the last bytes is requested
                $c_start = $size - substr($range, 1);
            }
            else {

                $range  = explode('-', $range);
                $c_start = $range[0];
                $c_end   = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
            }
            /* Check the range and make sure it's treated according to the specs.
             * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
             */
            // End bytes can not be larger than $end.
            $c_end = ($c_end > $end) ? $end : $c_end;
            // Validate the requested range and return an error if it's not correct.
            if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {

                header('HTTP/1.1 416 Requested Range Not Satisfiable');
                header("Content-Range: bytes $start-$end/$size");
                // (?) Echo some info to the client?
                exit;
            }
            $start  = $c_start;
            $end    = $c_end;
            $length = $end - $start + 1; // Calculate new content length
            header('HTTP/1.1 206 Partial Content');
        }
        // Notify the client the byte range we'll be outputting
        header("Content-Range: bytes $start-$end/$size");
        header("Content-Length: $length");

        return [$start,$end];
    }

一个好用的php id加密解密类,适用于隐藏用户真实id。hashids

效果 <?php use Hashids\Hashids; $hashids = new Hashids(); // no padding $hashids->encode(1); #结果 jR #指定返回10个字符长度的加密串 $hashids...

阅读全文

yum 安装redis5

更新yum源 # EPEL的全称叫 Extra Packages for Enterprise Linux 。EPEL是由 Fedora 社区打造,为 RHEL 及衍生发行版如 CentOS、Scientific Linux 等提供高质...

阅读全文

nginx 解析php conf配置文件

本博客的nginx 配置文件 server { listen 80;#80和443端口同时监听 listen 443 ssl; server_name www.koukousky.com koukousky.com...

阅读全文

欢迎留言