/ 从远程URL中获取媒体(如 mp4 mp3)的内容 @param mixed $file_url @param mixed $media_type @param mixed $curl_time_out @throws Exception @return mixed / public static function getRemoteMediaContent($file_url = '', $media_type = "Content-Type: video/mp4", $curl_time_out = 600000) { if (empty($file_url)) { throw new Exception('请传入远程url地址', Response::PARAM_ERROR); } $parse_bool = parse_url($file_url); if ($parse_bool === false) { throw new Exception('请传入有效的远程url地址', Response::PARAM_ERROR); } ini_set('max_execution_time', 0); $useragent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36"; //开一个ch 用来获取资源HTTP头信息(紧张获取视频长度) $ch = curl_init(); // TRUE 会输出所有的信息,写入到STDERR,或在CURLOPT_STDERR中指定的文件。 curl_setopt($ch, CURLOPT_VERBOSE, 1); //许可 cURL 函数实行的最长秒数 curl_setopt($ch, CURLOPT_TIMEOUT, $curl_time_out); //须要获取的 URL 地址,也可以在curl_init() 初始化会话的时候 curl_setopt($ch, CURLOPT_URL, $file_url); //TRUE 时将会根据做事器返回 HTTP 头中的 "Location: " 重定向。 //(把稳:这是递归的,"Location: " 发送几次就重定向几次,除非设置了 CURLOPT_MAXREDIRS,限定最大重定向次数。)。 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 启用时会将头文件的信息作为数据流输出(把稳这里第一步只须要获取资源HTTP头信息 紧张是为了得到内容的长度) curl_setopt($ch, CURLOPT_HEADER, true); // TRUE 逼迫获取一个新的连接,而不是缓存中的连接 curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // FALSE 禁止 cURL 验证对等证书(peer'scertificate)。要验证的交流证书可以在 CURLOPT_CAINFO 选项中设置,或在 CURLOPT_CAPATH中设置证书目录 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); //向做事器发送,包含了访问者系统引擎版本、浏览器信息的字段信息。 //一样平常做事器识别出是爬虫要求,会谢绝访问。以是此时设置User-Agent,可以将爬虫伪装成用户通过浏览器访问。 curl_setopt($ch, CURLOPT_USERAGENT, $useragent); // TRUE 时将不输出 BODY 部分。同时 Mehtod 变成了 HEAD。修正为 FALSE 时不会变成 GET curl_setopt($ch, CURLOPT_NOBODY, true); //TRUE 将curl_exec()获取的信息以字符串返回,而不是直接输出 //这里我们不须要关心 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //实行 cURL 会话 这里我们只关心头信息 以是不须要获取返回的内容 curl_exec($ch); //获取一个cURL连接资源句柄的信息 这里紧张用来读取长度 //-- CURLINFO_CONTENT_LENGTH_DOWNLOAD 从Content-Length: field中读取的下载内容长度 $filesize = $length = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); //发送要求的媒体头类型 header($media_type); //------ 获取资源长度告一段落 以下用于获取媒体视频的二进制内容------ //统共吸收的数据大小 header("Content-length: " . $filesize); //吸收的数据类型是 字节类型 即二进制 header('Accept-Ranges: bytes'); $partialContent = false; $offset = 0; //读取数据的初始位置 if (isset($_SERVER['HTTP_RANGE'])) { $partialContent = true; //得到初始位置和数据长度 preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches); $offset = intval($matches[1]); $length = $filesize - $offset - 1; / 断点续传: 便是从文件上次中断的地方开始重新下载或上传,当下载或上传文件的时候,如果没有实现断点续传功能,那么每次涌现非常或者用户主动的停息,都会去重头下载, 这样很摧残浪费蹂躏韶光。以是断点续传的功能就应运而生了。要实现断点续传的功能,须要客户端记录下当前的下载或上传进度, 并在须要续传的时候关照做事端本次须要下载或上传的内容片段。 HTTP的要求上定义了断点续传干系的HTTP头Range字段和Content-Range字段。 比如说客户端在Header中设置Range=bytes22223333- 表示文件从22223333字节开始传,前面的字节不用传了。 做事器收到要求,返回206 Partial Content。 Content-Length=44445555,Content-Range=bytes22223333-44445554/44445555 / //Chrome在对付MP3文件的访问,返回的都是206 Partial Content header('HTTP/1.1 206 Partial Content'); //每次吸收数据的的范围 header('Content-Range: bytes ' . $offset . '-' . ($offset + $length) . '/' . $filesize); } //重新开一个ch 用来获取内容 $ch = curl_init(); //如果支持分段发送数据 if ($partialContent && isset($_SERVER['HTTP_RANGE'])) { //获取上次的范围 preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches); $offset = intval($matches[1]); //开始位置 $length = $filesize - $offset - 1; //获取长度 //发送带有Range的要求头 $headers = ['Range: bytes=' . $offset . '-' . ($offset + $length) . '']; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); } curl_setopt($ch, CURLOPT_VERBOSE, 1); curl_setopt($ch, CURLOPT_TIMEOUT, $curl_time_out); curl_setopt($ch, CURLOPT_URL, $file_url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 启用时会将头文件的信息作为数据流输出(这里只须要获取内容 以是设置为false) curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_USERAGENT, $useragent); // TRUE 时将不输出 BODY 部分。同时 Mehtod 变成了 HEAD。修正为 FALSE 时不会变成 GET [ 这里我们不须要输出头信息] curl_setopt($ch, CURLOPT_NOBODY, false); // TRUE 将curl_exec()获取的信息以字符串返回,而不是直接输出 //这里我们须要直接输出二进制数据 curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); //实行 cURL 会话 curl_exec($ch); }
