<?php
/**
* Send File
*
* @author: Legend (legendsky@hotmail.com)
* @link: http://www.ugia.cn/?p=109
* @description: Send file to Client
* @version: 1.0
*
* @param string $fileName file name or path
* @param string $fancyName The custom file name, NULL to use filename
* @param boolean $forceDownload whether to force a download
* @param integer $speedLimit speed limit, in bytes, 0 is unrestricted, Windows Server is not supported
* @param string $ $contentType file type, default to Application/octet-stream
*
* @return Boolean
*/
function SendFile ($fileName, $fancyName = ', $forceDownload = true, $speedLimit = 0, $contentType = ')
{
if (!is_readable ($fileName))
{
Header ("http/1.1 404 Not Found");
return false;
}
$fileStat = stat ($fileName);
$lastModified = $fileStat [' Mtime '];
$MD 5 = MD5 ($fileStat [' Mtime ']. ='. $fileStat [' ino ']. ' ='. $fileStat [' size ']);
$etag = ' "'. $MD 5. '-' . CRC32 ($MD 5). '"';
Header (' last-modified: ' Gmdate ("D, D M Y h:i:s", $lastModified). ' GMT ');
Header ("ETag: $etag");
if (Isset ($_server[' http_if_modified_since ')) && strtotime ($_server[' http_if_modified_since ']) >= $ LastModified)
{
Header ("http/1.1 304 not Modified");
return true;
}
if (Isset ($_server[' http_if_unmodified_since ')) && strtotime ($_server[' http_if_unmodified_since ']) < $ LastModified)
{
Header ("http/1.1 304 not Modified");
return true;
}
if (Isset ($_server[' Http_if_none_match ')) && $_server[' http_if_none_match '] = = $etag)
{
Header ("http/1.1 304 not Modified");
return true;
}
if ($fancyName = = ")
{
$fancyName = basename ($fileName);
}
if ($contentType = = ")
{
$contentType = ' Application/octet-stream ';
}
$fileSize = $fileStat [' Size '];
$contentLength = $fileSize;
$isPartial = false;
if (Isset ($_server[' Http_range '))
{
if (Preg_match ('/^bytes= (d*)-(d*) $/', $_server[' Http_range '], $matches))
{
$startPos = $matches [1];
$endPos = $matches [2];
if ($startPos = = ' && $endPos = = ')
{
return false;
}
if ($startPos = = ")
{
$startPos = $fileSize-$endPos;
$endPos = $fileSize-1;
}
else if ($endPos = = ")
{
$endPos = $fileSize-1;
}
$startPos = $startPos < 0? 0: $startPos;
$endPos = $endPos > $fileSize-1? $fileSize-1: $endPos;
$length = $endPos-$startPos + 1;
if ($length < 0)
{
return false;
}
$contentLength = $length;
$isPartial = true;
}
}
/Send Headers
if ($isPartial)
{
header (' http/1.1 206 Partial Content ');
Header ("Content-range:bytes $startPos-$endPos/$fileSize");
}
Else
{
header ("http/1.1 OK");
$startPos = 0;
$endPos = $contentLength-1;
}
Header (' Pragma:cache ');
Header (' Cache-control:public, must-revalidate, max-age=0 ');
Header (' accept-ranges:bytes ');
Header (' Content-type: '. $contentType);
Header (' Content-length: '. $contentLength);
if ($forceDownload)
{
Header (' Content-disposition:attachment filename= '. Rawurlencode ($fancyName). "");//Chinese characters automatically convert to URL code
Header (' Content-disposition:attachment filename= "'. $fancyName. '"');
}
Header ("Content-transfer-encoding:binary");
$bufferSize = 2048;
if ($speedLimit!= 0)
{
$packetTime = Floor ($bufferSize * 1000000/$speedLimit);
}
$bytesSent = 0;
$fp = fopen ($fileName, "RB");
Fseek ($fp, $startPos);
Fpassthru ($FP);
while ($bytesSent < $contentLength &&!feof ($fp) && connection_status () = 0)
{
if ($speedLimit!= 0)
{
List ($usec, $sec) = Explode ("", Microtime ());
$outputTimeStart = ((float) $usec + (float) $sec);
}
$readBufferSize = $contentLength-$bytesSent < $bufferSize? $contentLength-$bytesSent: $bufferSize;
$buffer = Fread ($fp, $readBufferSize);
Echo $buffer;
Ob_flush ();
Flush ();
$bytesSent + + $readBufferSize;
if ($speedLimit!= 0)
{
List ($usec, $sec) = Explode ("", Microtime ());
$outputTimeEnd = ((float) $usec + (float) $sec);
$useTime = ((float) $outputTimeEnd-(float) $outputTimeStart) * 1000000;
$sleepTime = Round ($packetTime-$useTime);
if ($sleepTime > 0)
{
Usleep ($sleepTime);
}
}
}
return true;
}
?>