• 技术文章 >php教程 >php手册

    php 超大文件下载程序[http 缓存协商,Etag标记,断点续传]

    2016-06-13 11:23:25原创1260

    002 $file_path = './download/download_cn.rar';

    003

    004 //使用方法

    005 downFile($file_path);

    006

    007 // 服务器文件路径,下载文件名字(默认为服务器文件名),是否许可用户下载方式(默认可选),速度限制(默认自动),文件类型(默认所有)

    008 function downFile($fileName, $fancyName = '', $forceDownload = true, $speedLimit = 0, $contentType = '') {

    009 if (!is_readable($fileName))

    010 {

    011 header("HTTP/1.1 404 Not Found");

    012 return false;

    013 }

    014

    015 $fileStat = stat($fileName);

    016 $lastModified = $fileStat['mtime'];

    017

    018 $md5 = md5($fileStat['mtime'] .'='. $fileStat['ino'] .'='. $fileStat['size']);

    019 $etag = '"' . $md5 . '-' . crc32($md5) . '"';

    020

    021 header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastModified) . ' GMT');

    022 header("ETag: $etag");

    023

    024 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified)

    025 {

    026 header("HTTP/1.1 304 Not Modified");

    027 return true;

    028 }

    029

    030 if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) < $lastModified)

    031 {

    032 header("HTTP/1.1 304 Not Modified");

    033 return true;

    034 }

    035

    036 if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag)

    037 {

    038 header("HTTP/1.1 304 Not Modified");

    039 return true;

    040 }

    041

    042 if ($fancyName == '')

    043 {

    044 $fancyName = basename($fileName);

    045 }

    046

    047 if ($contentType == '')

    048 {

    049 $contentType = 'application/octet-stream';

    050 }

    051

    052 $fileSize = $fileStat['size'];

    053

    054 $contentLength = $fileSize;

    055 $isPartial = false;

    056

    057 if (isset($_SERVER['HTTP_RANGE']))

    058 {

    059 if (preg_match('/^bytes=(d*)-(d*)$/', $_SERVER['HTTP_RANGE'], $matches))

    060 {

    061 $startPos = $matches[1];

    062 $endPos = $matches[2];

    063

    064 if ($startPos == '' && $endPos == '')

    065 {

    066 return false;

    067 }

    068

    069 if ($startPos == '')

    070 {

    071 $startPos = $fileSize - $endPos;

    072 $endPos = $fileSize - 1;

    073 }

    074 else if ($endPos == '')

    075 {

    076 $endPos = $fileSize - 1;

    077 }

    078

    079 $startPos = $startPos < 0 ? 0 : $startPos;

    080 $endPos = $endPos > $fileSize - 1 ? $fileSize - 1 : $endPos;

    081

    082 $length = $endPos - $startPos + 1;

    083

    084 if ($length < 0)

    085 {

    086 return false;

    087 }

    088

    089 $contentLength = $length;

    090 $isPartial = true;

    091 }

    092 }

    093

    094 // send headers

    095 if ($isPartial)

    096 {

    097 header('HTTP/1.1 206 Partial Content');

    098 header("Content-Range: bytes $startPos-$endPos/$fileSize");

    099

    100 }

    101 else

    102 {

    103 header("HTTP/1.1 200 OK");

    104 $startPos = 0;

    105 $endPos = $contentLength - 1;

    106 }

    107

    108 header('Pragma: cache');

    109 header('Cache-Control: public, must-revalidate, max-age=0');

    110 header('Accept-Ranges: bytes');

    111 header('Content-type: ' . $contentType);

    112 header('Content-Length: ' . $contentLength);

    113

    114 if ($forceDownload)

    115 {

    116 header('Content-Disposition: attachment; filename="' . rawurlencode($fancyName). '"');

    117 }

    118

    119 header("Content-Transfer-Encoding: binary");

    120

    121 $bufferSize = 2048;

    122

    123 if ($speedLimit != 0)

    124 {

    125 $packetTime = floor($bufferSize * 1000000 / $speedLimit);

    126 }

    127

    128 $bytesSent = 0;

    129 $fp = fopen($fileName, "rb");

    130 fseek($fp, $startPos);

    131 while ($bytesSent < $contentLength && !feof($fp) && connection_status() == 0 )

    132 {

    133 if ($speedLimit != 0)

    134 {

    135 list($usec, $sec) = explode(" ", microtime());

    136 $outputTimeStart = ((float)$usec + (float)$sec);

    137 }

    138

    139 $readBufferSize = $contentLength - $bytesSent < $bufferSize ? $contentLength - $bytesSent : $bufferSize;

    140 $buffer = fread($fp, $readBufferSize);

    141

    142 echo $buffer;

    143

    144 ob_flush();

    145 flush();

    146

    147 $bytesSent += $readBufferSize;

    148

    149 if ($speedLimit != 0)

    150 {

    151 list($usec, $sec) = explode(" ", microtime());

    152 $outputTimeEnd = ((float)$usec + (float)$sec);

    153

    154 $useTime = ((float) $outputTimeEnd - (float) $outputTimeStart) * 1000000;

    155 $sleepTime = round($packetTime - $useTime);

    156 if ($sleepTime > 0)

    157 {

    158 usleep($sleepTime);

    159 }

    160 }

    161 }

    162 return true;

    163 }

    164 ?>


    php入门到就业线上直播课:查看学习

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    上一篇:php 一维数组排序与多维数组排序 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• smarty模板引擎从php中获取数据的方法,smarty模板• PHP类中的魔术方法(Magic Method)简明总结,magicmethod• php利用新浪接口查询ip获取地理位置• mysql 数据备份类代码• PHP之判断用户语言跳转网页
    1/1

    PHP中文网