在使用php + jsquery + javascript(例如index.php)构建的HTML页面上,视频标签具有另一个php页面的源,带有GET字段指定加载哪个视频(例如:"getfile.php ?文件"= 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"到"max-age/Expires"的详细信息)
- 视频#2按钮
- 等待视频#2播放完毕(Fiddler更新缓存信息)
- 视频#1按钮
在Chrome上,结果是视频#1立即开始播放(缓冲条显示一半加载,这是我在视频开始时看到的最多)。Fiddler没有向服务器显示一个新的"getfile"请求。
在IE 11中,有一个延迟,而视频#1缓冲(缓冲条显示零加载在视频开始)。Fiddler向服务器显示一个新的"getfile"请求。
IE的缓存设置为"自动"。(临时互联网文件/检查存储页面的新版本="自动")。缓存大小为250mb,每个视频约6mb,并且在开始测试之前清空缓存。
确认URL是完全相同的(根据fiddler,并在javascript中使用警告弹出)
问:还有什么可能影响IE无法缓存这些视频?
图片,通过相同的url获得,但具有不同的查询字段字段值,和不同的内容类型头,在IE缓存:如果退出浏览器,并重新启动浏览器,并去同一页面,Fiddler不显示任何"/getfile.php?Fileid =333"请求这些图像。(它确实显示了缓存清空后第一次加载页面时的请求)
php代码执行的唯一变化(对于图像和视频)是一个单独的if/else if语句,它控制发出什么Content-Type头。
也许是IE 11的缓存策略不缓存视频?
逻辑确实发出一个带有文件大小的Content-Length头,并且客户端internet选项缓存(250 mb)比文件大小(6 mb)大得多,因此它"应该"能够缓存它。磁盘空闲空间是多少gb
更新# 2
- 重新启动IE,使用安全选项卡关闭或打开"启用保护模式"后,不会改变上述结果。
- 将磁盘空间增加到最大(1024 MB)不会改变上述结果。
- 设置IE的策略为"检查存储页面的新版本:Never"似乎不"粘":当关闭Internet选项,然后重新打开它,单选按钮已返回到"自动"。
- …
- 在IE测试确认缓存仍然在Chrome中正常工作后重复Chrome测试。
更新# 3
服务器上的php代码不测试HTTP_IF_MODIFIED_SINCE;我没有发送Last-Modified header。我以为maxage就足够了。如果存在Last-Modified, IE可能会更聪明地缓存视频文件。如果您有过在慢速服务器连接上处理视频的经验,并且成功地使用了一组特定的标头,那么您使用的方法的答案将是有用的。
试试吧,来自http://php.net/manual/en/function.header.php#85146:
$last_modified_time = filemtime($file);
$etag = md5_file($file);
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");
header("Etag: $etag");
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time ||
trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
header("HTTP/1.1 304 Not Modified");
exit;
}