首页后端开发PHPphp断点续传原理是什么,怎么使用断点续传

php断点续传原理是什么,怎么使用断点续传

时间2024-03-25 05:40:03发布访客分类PHP浏览1398
导读:这篇文章主要给大家介绍“php断点续传原理是什么,怎么使用断点续传”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“php断点续传原理是什么,怎么使用断点续传”文章能对大家有...
这篇文章主要给大家介绍“php断点续传原理是什么,怎么使用断点续传”的相关知识,下文通过实际案例向大家展示操作过程,内容简单清晰,易于学习,有这方面学习需要的朋友可以参考,希望这篇“php断点续传原理是什么,怎么使用断点续传”文章能对大家有所帮助。



 

一、断点续传原理

所谓断点续传,也就是要从文件已经下载的地方开始继续下载。在以前版本的 HTTP 协议是不支持断点的,HTTP/1.1 开始就支持了。一般断点下载时才用到 Range 和 Content-Range 实体头。

不使用断点续传

get /down.zip http/1.1
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: mozilla/4.0 (compatible;
     msie 5.01;
     windows nt 5.0)
connection: keep-alive

服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:

HTTP/1.1 200 Ok
content-length=106786028
accept-ranges=bytes
date=mon, 30 apr 2001 12:56:11 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:56:11 gmt

使用断点续传

GET /down.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=2000070-
Accept: text/html, image/gif, image/jpeg, *;
     q=.2, */*;
 q=.2

多了这么一行Range: bytes=2000070-

这一行的意思就是告诉服务器down.zip这个文件从2000070字节开始传,前面的字节不用传了。
Range的完整格式是:

Range: bytes=startOffset-targetOffset/sum [表示从startOffset读取,一直读取到targetOffset位置,读取总数为sum直接]
 
Range: bytes=startOffset-targetOffset [字节总数也可以去掉]

服务器收到这个请求以后,返回的信息如下:

HTTP/1.1 206 Partial Content
content-length=106786028
content-range=bytes 2000070-106786027/106786028
date=mon, 30 apr 2001 12:55:20 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:55:20 gmt

和前面服务器返回的信息比较一下,就会发现增加了一行:

Content-Range=bytes 2000070-106786027/106786028

返回的代码也改为206了,而不再是200了。

HTTP/1.1 206 Partial Content

知道了以上原理,就可以进行断点续传的编程了。

二、PHP实现

/** php下载类,支持断点续传
 * download: 下载文件
 * setSpeed: 设置下载速度
 * getRange: 获取header中Range
 */
 
class FileDownload{

 
 /** 下载
 * @param String $file 要下载的文件路径
 * @param String $name 文件名称,为空则与下载的文件名称一样
 * @param boolean $reload 是否开启断点续传
 */
 public function download($file, $name='', $reload=false){
    
 $fp = @fopen($file, 'rb');

 if($fp){

 if($name==''){
    
 $name = basename($file);

 }
    
 $header_array = get_headers($file, true);
    
 //var_dump($header_array);
    die;

 // 下载本地文件,获取文件大小
 if (!$header_array) {
    
 $file_size = filesize($file);

 }
 else {
    
 $file_size = $header_array['Content-Length'];

 }
    
 $ranges = $this->
    getRange($file_size);
    
 $ua = $_SERVER["HTTP_USER_AGENT"];
    //判断是什么类型浏览器
 header('cache-control:public');
    
 header('content-type:application/octet-stream');
     
 
 $encoded_filename = urlencode($name);
    
 $encoded_filename = str_replace("+", "%20", $encoded_filename);

 
 //解决下载文件名乱码
 if (preg_match("/MSIE/", $ua) || preg_match("/Trident/", $ua) ){
     
 header('Content-Disposition: attachment;
     filename="' .$encoded_filename . '"');

 }
 else if (preg_match("/Firefox/", $ua)) {
    
 header('Content-Disposition: attachment;
     filename*="utf8\'\'' . $name . '"');

 }
else if (preg_match("/Chrome/", $ua)) {
    
 header('Content-Disposition: attachment;
     filename="' . $encoded_filename . '"');

 }
 else {
    
 header('Content-Disposition: attachment;
     filename="' . $name . '"');

 }
    
 //header('Content-Disposition: attachment;
     filename="' . $name . '"');
    
 
 if($reload &
    &
 $ranges!=null){
     // 使用续传
 header('HTTP/1.1 206 Partial Content');
    
 header('Accept-Ranges:bytes');
    
 
 // 剩余长度
 header(sprintf('content-length:%u',$ranges['end']-$ranges['start']));
    
 
 // range信息
 header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size));
    
 //file_put_contents('test.log',sprintf('content-length:%u',$ranges['end']-$ranges['start']),FILE_APPEND);
    
 // fp指针跳到断点位置
 fseek($fp, sprintf('%u', $ranges['start']));

 }
else{
    
 file_put_contents('test.log','2222',FILE_APPEND);
    
 header('HTTP/1.1 200 OK');
    
 header('content-length:'.$file_size);

 }

 
 while(!feof($fp)){
    
 //echo fread($fp, round($this->
    _speed*1024,0));
    
 //echo fread($fp, $file_size);
    
 echo fread($fp, 4096);
    
 ob_flush();

 }
    
 
 ($fp!=null) &
    &
     fclose($fp);

 }
else{
    
 return '';

 }

 }

 
 /** 设置下载速度
 * @param int $speed
 */
 public function setSpeed($speed){
    
 if(is_numeric($speed) &
    &
     $speed>
    16 &
    &
 $speed4096){
    
 $this->
    _speed = $speed;

 }

 }

 
 /** 获取header range信息
 * @param int $file_size 文件大小
 * @return Array
 */
 private function getRange($file_size){
    
 //file_put_contents('range.log', json_encode($_SERVER), FILE_APPEND);
    
 if(isset($_SERVER['HTTP_RANGE']) &
    &
 !empty($_SERVER['HTTP_RANGE'])){
    
 $range = $_SERVER['HTTP_RANGE'];
    
 $range = preg_replace('/[\s|,].*/', '', $range);
    
 $range = explode('-', substr($range, 6));

 if(count($range)2){
    
 $range[1] = $file_size;

 }
    
 $range = array_combine(array('start','end'), $range);

 if(empty($range['start'])){
    
 $range['start'] = 0;

 }

 if(empty($range['end'])){
    
 $range['end'] = $file_size;

 }
    
 return $range;

 }
    
 return null;

 }

}
    
 
$obj = new FileDownload();
    
$obj->
    download('http://down.golaravel.com/laravel/laravel-master.zip','', true);
    

以上就是php实现断点续传大文件示例代码的详细内容,更多关于php 断点续传大文件的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
  • PHP大文件分割分片上传实现代码
  • PHP大文件及断点续传下载实现代码
  • PHP下载大文件失败并限制下载速度的实例代码
  • PHP超低内存遍历目录文件和读取超大文件的方法
  • 详解PHP多个进程配合redis的有序集合实现大文件去重
  • PHP如何通过表单直接提交大文件详解
  • PHP大文件分片上传的实现方法
  • php下载远程大文件(获取远程文件大小)的实例
  • 详解PHP如何读取大文件

关于“php断点续传原理是什么,怎么使用断点续传”的内容就介绍到这,感谢各位的阅读,相信大家对php断点续传原理是什么,怎么使用断点续传已经有了进一步的了解。大家如果还想学习更多知识,欢迎关注网络,小编将为大家输出更多高质量的实用文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: php断点续传原理是什么,怎么使用断点续传
本文地址: https://pptw.com/jishu/652575.html
PHP如何修改php.ini文件上传大小的配置呢 Vue中的修饰符有几种,基本用法是什么

游客 回复需填写必要信息