php 超大文件下载程序[http 缓存协商,Etag标记,断点续传]
<?php教程
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 ?>
本文链接:http://www.phprm.com/frame/php1005012.html
收藏随意^^请保留教程地址.