在我在网上发布的各种问题都没有被点击之后,我们又对此进行了破解,并能够弄清楚。
原来这是 Media.php 类文件 ( /cake/libs/view/media.php
) 中的一个问题,它对 HTTP_RANGE 标头值的预期以及它如何格式化后续标头。首先,这是原始的相关代码片段:
$httpRange = env('HTTP_RANGE');
if (isset($httpRange)) {
list($toss, $range) = explode('=', $httpRange);
$size = $fileSize - 1;
$length = $fileSize - $range;
$this->_header(array(
'HTTP/1.1 206 Partial Content',
'Content-Length: ' . $length,
'Content-Range: bytes ' . $range . $size . '/' . $fileSize));
fseek($handle, $range);
}
请注意list()
调用,它填充了一个$range
值,然后将其用作数字。但是,在进一步调试标头调用之后,我们注意到 HTTP_RANGE 值实际上是给出的,Range: bytes=0-1000
因为给定的数字范围取决于请求。我们进行了以下更改(并在媒体视图调用中将下载布尔值设置为 true),瞧,iOS 设备上的工作视频。
$httpRange = env('HTTP_RANGE');
if (isset($httpRange)) {
$start = 0; //start byte
$end = $fileSize - 1; //end byte
$length = $fileSize; //content length
$c_start = $start; //default value
$c_end = $end; //default value
list($toss, $range) = explode('=', $httpRange); //extract range
//grab range value(s)
if ($range[0] == '-') {
$c_start = $fileSize - substr($range, 1);
} else {
$range = explode('-', $range);
$c_start = $range[0];
$c_end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $fileSize;
}
//validate end byte
$c_end = ($c_end > $end) ? $end : $c_end;
//set new values
$start = $c_start;
$end = $c_end;
$length = $end - $start + 1;
$this->_header(array(
'HTTP/1.1 206 Partial Content',
'Content-Length: ' . $length,
'Content-Range: bytes ' . $start . '-' . $end . '/' . $fileSize));
fseek($handle, $start);
}
请注意,这包含了本文附录 A 中的大部分逻辑,它处理了各种情况。(最初我们避开了大部分这种逻辑,虽然播放效果很好,但一旦在 iOS 设备上到达文件末尾,它似乎有点不稳定。)