单个PHP“退出;”声明阻止Safari中的HTML5视频

时间:2010-06-24 22:35:23

标签: php video safari

奇怪的错误:在提供视频文件的PHP脚本中,在发送“video / mp4”标题并输出MP4文件之前,我有一些测试条件(验证令牌,确保文件存在等)。

如果任何测试失败,$fail将被赋予非假值。

在测试结束时,有if声明:

if ($fail) {
    exit;
}

此代码在Chrome中按预期工作,但在Safari中无效。但是(如果我只是注释掉exit;,请相信我,我相信我的每一个方向),如:

if ($fail) {
    //exit;
}

...代码在Safari中完美运行 - 视频立即开始加载。

我确信永远不会输入if块,否则脚本会停止执行,我不会看到video/mp4标题(更不用说,它不会起作用)在Chrome中)。此外,无论PHP在幕后做什么,都应该对浏览器完全透明。我想也许输出存在一些问题,但如果我在标题之前输出任何内容,我会收到警告。

我已经连续几天看到这种行为 - 我难以置信地检查了25次。

肯定有一些我想念的东西?

更新

为了澄清这个问题,我改变了一下代码:

$fail = true;
if ($fail) {
    die('Fail');
}

现在我们保证会点击die()语句,并输出“Fail”。以下是标题,如Safari所示:

Connection:Keep-Alive
Content-Type:text/html
Date:Thu, 24 Jun 2010 23:31:28 GMT
Keep-Alive:timeout=10, max=29
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
Transfer-Encoding:Identity
X-Powered-By:PHP/5.2.13

(“失败”也按预期输出。)

现在,当我发表评论$fail = true;时,标题会更改为:

Connection:Keep-Alive
Content-Length:47406944
Content-Type:video/mp4
Date:Thu, 24 Jun 2010 23:32:58 GMT
Keep-Alive:timeout=10, max=30
Server:Apache/2.2.15 (CentOS) mod_ssl/2.2.15 0.9.8l DAV/2 mod_auth_passthrough/2.1 FrontPage/5.0.2.2635
X-Powered-By:PHP/5.2.13

但视频仍然无法播放! (QuickTime徽标上面有问号。)

我认为足够的证据表明$fail仍然是假的,die()永远不会被执行。

现在,得到这个:如果我再次发表评论die()(功能上等同于exit),那么我的最终代码为:

//$fail = true;
if ($fail) {
    //die('Fail');
}

...视频在Safari中播放!

更新2

如果我将代码更改为:

$fail = false;
if ($fail) {
    die('Fail');
}

...绝对保证$failfalse,它在Safari中播放!

这种行为对我没有意义,b / c如果由于我的某个验证条件而设置$fail,那么它将永远不会输出video/mp4标头,就像我明确设置{ {1}}到$fail - 相反,它会输出一个带有“失败”字样的true页面 - 对吗?

更新3

以下是所有相关代码,只是为了完全清楚:

text/html

希望最后更新/摘要

这个问题可能已经太长了,但我想我最后一次尝试总结这是多么奇怪。有3个不同的回答:

1)如果我在// verify $fail = false; $token = false; $file_name = [rest assured that $file_name is correct]; if (!$file_name) { $fail = true; } else { $file_name = '../video/'.$file_name; } if (!isset($_REQUEST['ts'])) { $fail = true; } if (isset($_POST['token']) || isset($_GET['token'])) { $token = isset($_POST['token']) ? $_POST['token'] : $_GET['token']; } else if (isset($_COOKIE['token'])) { $token = $_COOKIE['token']; } if ($token != md5(SALT_HASH.$_REQUEST['ts'])) { $fail = true; } if (((int)($_REQUEST['ts']) + 60 * 10) < mktime()) { $fail = true; } if (!is_file($file_name)) { $fail = true; } if ($fail) { die('Fail'); } // output $file_size = (string)(filesize($file_name)); header('Content-Type: video/mp4'); header('Content-Length: '.$file_size); readfile_chunked($file_name); exit; 之前硬连线$fail = true;,那么我有一个失败的基线,我得到一个if ($fail) die('Fail');标题,并按预期输出“失败”一词

2)如果我保留上面的代码,我会得到一个text/html标题,但Safari中的视频已损坏(它将在Chrome中播放)。

3)最后(这是基于我今天做的新测试),如果我在令牌验证条件中注释video/mp4,我会得到一个$fail = true;标题,视频会播放苹果浏览器。现在,我认为必须令牌验证有问题 - 但是当我在另一个测试中硬连线以在测试后回显$ fail的值时,它仍然是假的!从未输入条件(我也只是直接video/mp4而不是die('!'); - 我仍然会得到$fail = true;标题。

我简直无法相信注释掉永远不会被执行的代码会导致明显的响应 - 此外,在Chrome中播放,而不是在Safari中播放;无论服务器端发生什么,PHP应该对浏览器完全透明。

疯狂。

AHA!

我在我的脚本中添加了一些日志记录,结果发现,在提供HTML5视频时,浏览器会发出两个请求。

以下是来自Chrome的两个(成功)请求:

video/mp4

这是两个来自Safari(第一次成功,第二次失败):

Fri Jun 25 17:41:22 2010 Browser: [Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4] Fail: [0] Token: [83e50b519c0ed4662b6b7fabb8f6671e] Timestamp: [1277509282]
Fri Jun 25 17:41:22 2010 Verification passed

Fri Jun 25 17:41:22 2010 Browser: [Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.86 Safari/533.4] Fail: [0] Token: [83e50b519c0ed4662b6b7fabb8f6671e] Timestamp: [1277509282]
Fri Jun 25 17:41:22 2010 Verification passed

我现在必须出去,但我几乎可以肯定这种行为是bug的根源。出于某种原因,第二个Safari请求找不到令牌。

3 个答案:

答案 0 :(得分:3)

事实证明,浏览器在播放前向<video>源发出两个请求。我只看到第一次请求的标题,因此我的困惑。视频在Chrome中播放而不是Safari的原因是因为在Safari中发出第二个请求的代理(“QuickTime / 7.6.6(qtver = 7.6.6; cpu = IA32; os = Mac 10.6.4)”)显然可以读同样的$ _COOKIEs;而对于Chrome,$ _COOKIE在两个请求中都是完整的。

我仍然有一个严重的问题,因为视频只能在桌面浏览器上播放,而不能在iPhone上播放。我确定这不是编码问题,因为如果我直接访问MP4,它就可以正常运行;只有当视频通过PHP输出时才会出现问题。无论如何,这完全是另一个问题。

答案 1 :(得分:0)

它呈现空白页面的唯一原因是它确实进入了退出区;声明。你提到了一个身份验证令牌,在safari中测试时可能会丢失吗? Firebug和Safari的开发人员工具也可以帮助您进行调试(检查响应标头等)。

答案 2 :(得分:0)

如果没有video/mp4标头,服务器将发送默认内容类型标头,通常为text/html,某些浏览器可能会查看正在提供的内容并忽略MIME类型。

error_reporting(E_ALL);添加到脚本的开头,并使用firebug或类似方法检查正在发送的标头。