在使用php+jsquery+javascript(例如index.php)构建的HTML页面上,视频标记的源是另一个php页面,GET字段指定要加载的视频(例如“getfile.php?file=111”)。
按钮切换正在播放的视频;例如javascript
var video = document.getElementById('flyover');
var source = video.getElementsByTagName('source')[0];
source.setAttribute('src', "getfile.php?file=222");
getfile.php发出HTTP头,然后
fpassthru
文件内容的。
...
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename='.basename($file->FileName));
header('Content-Transfer-Encoding: binary');
$seconds_to_keep = ...
header ("Expires: " . gmdate("D, d M Y H:i:s", time() + $seconds_to_keep) . " GMT");
header('Cache-Control: public, max-age=' . $seconds_to_keep);
header('Content-Length: ' . filesize($filename));
fpassthru($fp);
exit;
用于确认标头的Fiddler代理:
# Result Protocol Host URL Body Caching Content-Type
47 200 HTTP ... /getfile.php?file=2639 10,113 public, max-age=31536000; Expires: Thu, 06 Aug 2015 20:20:30 GMT video/mp4
测试操作:
-
加载页面
-
等待视频#1播放完毕(Fiddler将缓存信息从“-1”更新为“最大年龄/过期”详细信息)
-
视频#2按钮
-
等待视频#2播放完毕(Fiddler更新缓存信息)
-
视频#1按钮
在Chrome上,结果是视频#1立即开始播放(缓冲条显示加载一半,这是我在视频开始时看到的最多的一次)。Fiddler不会向服务器显示新的“getfile”请求。
在IE 11上,视频#1缓冲时存在延迟(缓冲条显示视频开始时加载为零)。Fiddler确实向服务器显示了一个新的“getfile”请求。
IE的缓存设置为“自动”。(临时Internet文件/检查存储页面的更新版本=“自动”)。缓存大小为250 mb,每个视频约为6 mb,在开始测试之前,缓存已清空。
确认URL完全相同(根据fiddler的说法,并使用javascript中的警告弹出窗口)。
Q: 还有什么可能影响IE缓存这些视频的失败?
更新
图片,通过相同的url获取,但具有不同的查询字段fileid值和不同的Content-Type标头,在IE中进行缓存:如果退出浏览器,重新启动浏览器,并转到相同的页面,Fiddler不会显示这些图片的任何“/getfile.php?fileid=333”请求。(它确实在缓存清除后首次加载页面时显示了这些请求。)
在php代码中执行的唯一更改(对于图像和视频)是一个if/else-if语句,它控制发出什么Content-Type头。
也许IE 11的缓存策略是不缓存视频?
该逻辑确实会发出带有文件大小的Content-Length标头,并且客户端internet选项缓存(250 mbs)比文件大小(6 mbs)大得多,因此它“应该”能够缓存它。磁盘空间可用很多GB。
更新#2
-
使用“安全”选项卡关闭或打开“启用保护模式”后,重新启动IE不会改变上述结果。
-
将磁盘空间增加到最大值(1024 MB)不会改变上述结果。
-
将IE的策略设置为“检查存储页面的更新版本:从不”似乎不会“卡住”:当关闭“Internet选项”,然后重新打开它时,单选按钮已返回到“自动”。
-
...
-
在IE测试后重复Chrome测试,确认缓存在Chrome中仍然正常工作。
更新#3
服务器上的php代码未测试HTTP_IF_MODIFIED_SINCE;我没有发送Last Modified标头。我以为最大化就足够了。如果存在“上次修改”,IE可能会更聪明地缓存视频文件。如果您有过通过慢速服务器连接观看视频的经验,并且已经成功使用了一组特定的标头,那么您使用的方法的答案将非常有用。