Created
March 12, 2012 10:02
-
-
Save MSeven/2021002 to your computer and use it in GitHub Desktop.
http byte range file server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// check if the file actually exists. | |
if (file_exists($filePath)) { | |
//everything OK, log the access and start pushing the file. | |
$info = pathinfo($filePath); | |
$fileSize = filesize($filePath) - 1; | |
$fp = fopen($filePath, 'rb'); | |
// push it. | |
header("Expires: 0"); | |
header('Content-Type: ' . $this->extensionToMime($info['extension'])); | |
header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); | |
header("Pragma: no-cache"); | |
header("Accept-Ranges: 0-$fileSize"); | |
header("Content-Length: " . $fileSize); | |
if ($this->dispositionHeader) { | |
header('Content-Disposition: attachment; filename="' . $info['basename'] . '"'); | |
} | |
$start = 0; // Start byte | |
$end = $fileSize; // End byte | |
//get the HTTP_RANGE Header (required for iPad/HTML5 pseudostreaming) | |
$range = $request->getServer('HTTP_RANGE'); | |
// was the RANGE header actually set? | |
if ($range != NULL) { | |
$range = explode('=', $range); | |
// should be exactly 2 keys, and the request MUST be addressing by bytes. | |
if (count($range) == 2 && $range[0] == 'bytes') { | |
// now try to extract the start/end offsets. | |
$boundaries = explode('-', $range[1]); | |
// empty start defaults to 0 which is file_start. | |
$start = intval($boundaries[0]); | |
$end = intval($boundaries[1]); | |
// if end is empty, just push until file_end. | |
if ($end == 0) { | |
$end = $fileSize; | |
} | |
if ($end < $start || $end > $fileSize) { | |
header("Status: 416 Requested range not satisfiable"); | |
header("Content-Range: */$fileSize"); | |
return; | |
} | |
fseek($fp, $start); | |
header('HTTP/1.1 206 Partial Content'); | |
// Notify the client the byte range we'll be outputting | |
header("Content-Range: bytes $start-$end/$fileSize"); | |
} | |
} elseif ($request->getParam('start') != null) { | |
$start = intval(str_replace('.', '', $request->getParam('start', 0))); | |
if ($start < $end) { | |
fseek($fp, $start); | |
} else { | |
header("Status: 416 Requested range not satisfiable"); | |
return; | |
} | |
} | |
$currPos = $start; | |
// now push the requested file section to the client. | |
while (! feof($fp) && $currPos < $end) { | |
/** | |
* Chunks are the sections read from the file at once. | |
* This significantly reduces memory usage, since only one chunk resides | |
* in memory at one time. Choosing a small chunk size increases the php overhead though. | |
*/ | |
$chunk = 16 * 1024; | |
$currPos = ftell($fp); | |
// check if we would overshoot the requested byterange of we push the whole chunk. | |
if (($currPos + $chunk) > $end) { | |
//adjust the chunk size | |
$chunk = $end - $currPos; | |
// umm.. are we in the badlands already? | |
if ($chunk <= 0) { | |
break; | |
} | |
} | |
echo (fread($fp, $chunk)); | |
ob_flush(); | |
} | |
fclose($fp); | |
return; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment