注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

phperwuhan的博客

记载一个phper的历程!phperwuhan.blog.163.com

 
 
 

日志

 
 

[php]一个发送文件的函数  

2010-03-29 16:22:58|  分类: php |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

来源:http://www.ugia.cn/?p=109

这是前段时间在live-share.com上使用的文件发送函数,后来由于这种方式在高并发下负载过大,而放弃使用。此函数支持多线及断点续传,在非windows服务器下可限制速度,windows服务器因为不支持usleep函数,但用sleep函数效果不理想,所以放弃。此函数并不完全符合HTTP1.1标准,其中的断点续传部分没有考虑多个range的情况(事实上我还没见过哪个下载软件这么变态)。

下载: sendfile.php
  1. /**
  2. * 发送文件
  3. *
  4. * @author: legend(legendsky@hotmail.com)
  5. * @link: http://www.ugia.cn/?p=109
  6. * @description: send file to client
  7. * @version: 1.0
  8. *
  9. * @param string   $fileName      文件名称或路径
  10. * @param string   $fancyName     自定义的文件名,为空则使用filename
  11. * @param boolean  $forceDownload 是否强制下载
  12. * @param integer  $speedLimit    速度限制,单位为字节,0为不限制,不支持windows服务器
  13. * @param string   $$contentType  文件类型,默认为application/octet-stream
  14. *
  15. * @return boolean
  16. */
  17. function sendFile($fileName, $fancyName = '', $forceDownload = true, $speedLimit = 0, $contentType = '')
  18. {
  19.     if (!is_readable($fileName))
  20.     {
  21.         header("HTTP/1.1 404 Not Found");
  22.         return false;
  23.     }
  24.  
  25.     $fileStat = stat($fileName);
  26.     $lastModified = $fileStat['mtime'];
  27.    
  28.     $md5 = md5($fileStat['mtime'] .'='. $fileStat['ino'] .'='. $fileStat['size']);
  29.     $etag = '"' . $md5 . '-' . crc32($md5) . '"';
  30.  
  31.     header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastModified) . ' GMT');
  32.     header("ETag: $etag");
  33.    
  34.     if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified)
  35.     {
  36.         header("HTTP/1.1 304 Not Modified");
  37.         return true;
  38.     }
  39.  
  40.     if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) < $lastModified)
  41.     {
  42.         header("HTTP/1.1 304 Not Modified");
  43.         return true;
  44.     }
  45.  
  46.     if (isset($_SERVER['HTTP_IF_NONE_MATCH']) &&  $_SERVER['HTTP_IF_NONE_MATCH'] == $etag)
  47.     {
  48.         header("HTTP/1.1 304 Not Modified");
  49.         return true;
  50.     }
  51.  
  52.     if ($fancyName == '')
  53.     {
  54.         $fancyName = basename($fileName);
  55.     }
  56.    
  57.     if ($contentType == '')
  58.     {
  59.         $contentType = 'application/octet-stream';
  60.     }
  61.  
  62.     $fileSize = $fileStat['size'];  
  63.    
  64.     $contentLength = $fileSize;
  65.     $isPartial = false;
  66.  
  67.     if (isset($_SERVER['HTTP_RANGE']))
  68.     {
  69.         if (preg_match('/^bytes=(\d*)-(\d*)$/', $_SERVER['HTTP_RANGE'], $matches))
  70.         {   
  71.             $startPos = $matches[1];
  72.             $endPos = $matches[2];
  73.  
  74.             if ($startPos == '' && $endPos == '')
  75.             {
  76.                 return false;
  77.             }
  78.            
  79.             if ($startPos == '')
  80.             {
  81.                 $startPos = $fileSize - $endPos;
  82.                 $endPos = $fileSize - 1;
  83.             }
  84.             else if ($endPos == '')
  85.             {
  86.                 $endPos = $fileSize - 1;
  87.             }
  88.  
  89.             $startPos = $startPos < 0 ? 0 : $startPos;
  90.             $endPos = $endPos > $fileSize - 1 ? $fileSize - 1 : $endPos;
  91.  
  92.             $length = $endPos - $startPos + 1;
  93.  
  94.             if ($length < 0)
  95.             {
  96.                 return false;
  97.             }
  98.  
  99.             $contentLength = $length;
  100.             $isPartial = true;
  101.         }
  102.     }
  103.    
  104.     // send headers
  105.     if ($isPartial)
  106.     {
  107.         header('HTTP/1.1 206 Partial Content');
  108.         header("Content-Range: bytes $startPos-$endPos/$fileSize");
  109.        
  110.     }
  111.     else
  112.     {
  113.         header("HTTP/1.1 200 OK");
  114.         $startPos = 0;
  115.         $endPos = $contentLength - 1;
  116.     }
  117.  
  118.     header('Pragma: cache');
  119.     header('Cache-Control: public, must-revalidate, max-age=0');
  120.     header('Accept-Ranges: bytes');
  121.     header('Content-type: ' . $contentType);
  122.     header('Content-Length: ' . $contentLength);
  123.    
  124.     if ($forceDownload)
  125.     {
  126.         header('Content-Disposition: attachment; filename="' . rawurlencode($fancyName). '"');
  127.     }
  128.  
  129.     header("Content-Transfer-Encoding: binary");
  130.    
  131.     $bufferSize = 2048;
  132.  
  133.     if ($speedLimit != 0)
  134.     {
  135.         $packetTime = floor($bufferSize * 1000000 / $speedLimit);
  136.     }
  137.  
  138.     $bytesSent = 0;
  139.     $fp = fopen($fileName, "rb");
  140.     fseek($fp, $startPos);
  141.  
  142.     //fpassthru($fp);
  143.    
  144.     while ($bytesSent < $contentLength && !feof($fp) && connection_status() == 0 )
  145.     {
  146.         if ($speedLimit != 0)
  147.         {
  148.             list($usec, $sec) = explode(" ", microtime());
  149.             $outputTimeStart = ((float)$usec + (float)$sec);
  150.         }
  151.  
  152.         $readBufferSize = $contentLength - $bytesSent < $bufferSize ? $contentLength - $bytesSent : $bufferSize;
  153.         $buffer = fread($fp, $readBufferSize);       
  154.  
  155.         echo $buffer;
  156.  
  157.         ob_flush();
  158.         flush();
  159.  
  160.         $bytesSent += $readBufferSize;
  161.        
  162.         if ($speedLimit != 0)
  163.         {
  164.             list($usec, $sec) = explode(" ", microtime());
  165.             $outputTimeEnd = ((float)$usec + (float)$sec);
  166.            
  167.             $useTime = ((float) $outputTimeEnd - (float) $outputTimeStart) * 1000000;
  168.             $sleepTime = round($packetTime - $useTime);
  169.             if ($sleepTime > 0)
  170.             {
  171.                 usleep($sleepTime);
  172.             }
  173.         }
  174.     }
  175.    
  176.  
  177.     return true;
  178. }

demo: 下载:周杰伦-《千里之外》

<?php
sendFile
('./wp-data/jay_chou_-_outside_great_distance.mp3''outside_great_distance.mp3');
?>
  评论这张
 
阅读(342)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017