PHP使用range协议实现输出文件断点续传代码实例


Posted in PHP onJuly 04, 2014

range协议用途:一般是用在断点续传的时候,但是实际的用户很大,例如你的web server需要输出一个大文件,那么用range可以分段输出,缓解压力。同时在提供音乐视频等服务时可以缓冲下载,如果用户中途关闭,可以节约网络带宽。

<?php

// 文件名
$filename = $_GET ['filename'];

// 文件路径
$location = 'media/' . $filename;

// 后缀
$extension = substr ( strrchr ( $filename, '.' ), 1 );

if ($extension == "mp3") {
	$mimeType = "audio/mpeg";
} else if ($extension == "ogg") {
	$mimeType = "audio/ogg";
}

if (! file_exists ( $location )) {
	header ( "HTTP/1.1 404 Not Found" );
	return;
}

$size = filesize ( $location );
$time = date ( 'r', filemtime ( $location ) );

$fm = @fopen ( $location, 'rb' );
if (! $fm) {
	header ( "HTTP/1.1 505 Internal server error" );
	return;
}

$begin = 0;
$end = $size - 1;

if (isset ( $_SERVER ['HTTP_RANGE'] )) {
	if (preg_match ( '/bytes=\h*(\d+)-(\d*)[\D.*]?/i', $_SERVER ['HTTP_RANGE'], $matches )) {
		// 读取文件,起始节点
		$begin = intval ( $matches [1] );

		// 读取文件,结束节点
		if (! empty ( $matches [2] )) {
			$end = intval ( $matches [2] );
		}
	}
}

if (isset ( $_SERVER ['HTTP_RANGE'] )) {
	header ( 'HTTP/1.1 206 Partial Content' );
} else {
	header ( 'HTTP/1.1 200 OK' );
}

header ( "Content-Type: $mimeType" );
header ( 'Cache-Control: public, must-revalidate, max-age=0' );
header ( 'Pragma: no-cache' );
header ( 'Accept-Ranges: bytes' );
header ( 'Content-Length:' . (($end - $begin) + 1) );

if (isset ( $_SERVER ['HTTP_RANGE'] )) {
	header ( "Content-Range: bytes $begin-$end/$size" );
}

header ( "Content-Disposition: inline; filename=$filename" );
header ( "Content-Transfer-Encoding: binary" );
header ( "Last-Modified: $time" );

$cur = $begin;

// 定位指针
fseek ( $fm, $begin, 0 );

while ( ! feof ( $fm ) && $cur <= $end && (connection_status () == 0) ) {
	print fread ( $fm, min ( 1024 * 16, ($end - $cur) + 1 ) );
	$cur += 1024 * 16;
}

range协议官方文档:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

PHP 相关文章推荐
PHP学习笔记 IIS7下安装配置php环境
Oct 29 PHP
解析php中获取系统信息的方法
Jun 25 PHP
使用php实现快钱支付功能(涉及到接口)
Jul 01 PHP
php实现斐波那契数列的简单写法
Jul 19 PHP
PHP会话控制:Session与Cookie详解
Sep 27 PHP
ThinkPHP上使用多说评论插件的方法
Oct 31 PHP
php生成过去100年下拉列表的方法
Jul 20 PHP
分享PHP函数实现数字与文字分页代码
Jul 28 PHP
详解php中空字符串和0之间的关系
Oct 23 PHP
PHP面向对象之领域模型+数据映射器实例(分析)
Jun 21 PHP
PHP一个简单的无需刷新爬虫
Jan 05 PHP
PHP开发API接口签名生成及验证操作示例
May 27 PHP
PHP实现对文本数据库的常用操作方法实例演示
Jul 04 #PHP
成为好程序员必须避免的5个坏习惯
Jul 04 #PHP
windows7下安装php的php-ssh2扩展教程
Jul 04 #PHP
windows7下安装php的imagick和imagemagick扩展教程
Jul 04 #PHP
ThinkPHP框架任意代码执行漏洞的利用及其修复方法
Jul 04 #PHP
php实现批量压缩图片文件大小的脚本
Jul 04 #PHP
PHP实现的英文名字全拼随机排号脚本
Jul 04 #PHP
You might like
修改Zend引擎实现PHP源码加密的原理及实践
2008/04/14 PHP
php xml实例 留言本
2009/03/20 PHP
PHP json_encode中文乱码问题的解决办法
2013/09/09 PHP
ThinkPHP3.1新特性之对Ajax的支持更加完善
2014/06/19 PHP
关于PHP定时发送服务的解决办法
2017/04/23 PHP
PHP多个图片压缩成ZIP的方法
2020/08/18 PHP
php简单检测404页面的方法示例
2019/08/23 PHP
Array对象方法参考
2006/10/03 Javascript
IE和Firefox下javascript的兼容写法小结
2008/12/10 Javascript
基于JQUERY的两个ListBox子项互相调整的实现代码
2011/05/07 Javascript
浅谈Jquery为元素绑定事件
2015/04/27 Javascript
JS实现单击输入框弹出选择框效果完整实例
2015/12/14 Javascript
jQuery版AJAX简易封装代码
2016/09/14 Javascript
浅谈javascript中的 “ &amp;&amp; ” 和 “ || ”
2017/02/02 Javascript
Vue实现选择城市功能
2017/05/27 Javascript
JavaScrip数组删除特定元素的几种方法总结
2017/09/06 Javascript
详解Node.js利用node-git-server快速搭建git服务器
2017/09/27 Javascript
JS 事件机制完整示例分析
2020/01/15 Javascript
vuex管理状态仓库使用详解
2020/07/29 Javascript
小程序实现点击tab切换左右滑动
2020/11/16 Javascript
[00:09]DOTA2全国高校联赛 精彩活动引爆全场
2018/05/30 DOTA
[30:37]【全国守擂赛】第三周擂主赛 Dark Knight vs. Leopard Gaming
2020/05/04 DOTA
详解python中 os._exit() 和 sys.exit(), exit(0)和exit(1) 的用法和区别
2017/06/23 Python
Python实现判断一行代码是否为注释的方法
2018/05/23 Python
ubuntu 安装pyqt5和卸载pyQt5的方法
2020/03/24 Python
PyInstaller的安装和使用的详细步骤
2020/06/02 Python
python实现画图工具
2020/08/27 Python
《最大的麦穗》教学反思
2014/04/17 职场文书
学生上课看漫画的检讨书
2014/09/26 职场文书
教师党员个人整改措施
2014/10/27 职场文书
2014年教师学期工作总结
2014/11/08 职场文书
2014社区健康教育工作总结
2014/12/16 职场文书
2016大学生就业指导课心得体会
2016/01/15 职场文书
MySQL笔记 —SQL运算符
2022/01/18 MySQL
浅析python中特殊文件和特殊函数
2022/02/24 Python
SpringBoot中使用Redis作为全局锁示例过程
2022/03/24 Java/Android