function _cdn_transfer_file in CDN 6.2
Same name and namespace in other branches
- 7.2 cdn.basic.farfuture.inc \_cdn_transfer_file()
Variant of Drupal's file_transfer(), based on http://www.thomthom.net/blog/2007/09/php-resumable-download-server/ to support ranged requests as well.
Note: ranged requests that request multiple ranges are not supported. They are responded to with a 416. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html
1 call to _cdn_transfer_file()
File
- ./
cdn.basic.farfuture.inc, line 326 - Far Future expiration setting for basic mode.
Code
function _cdn_transfer_file($path) {
$fp = @fopen($path, 'rb');
$size = filesize($path);
// File size
$length = $size;
// Content length
$start = 0;
// Start byte
$end = $size - 1;
// End byte
// In case of a range request, seek within the file to the correct location.
if (isset($_SERVER['HTTP_RANGE'])) {
$c_start = $start;
$c_end = $end;
// Extract the string containing the requested range.
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
// If the client requested multiple ranges, repond with a 416.
if (strpos($range, ',') !== FALSE) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header("Content-Range: bytes {$start}-{$end}/{$size}");
exit;
}
// Case "Range: -n": final n bytes are requested.
if ($range[0] == '-') {
$c_start = $size - substr($range, 1);
}
else {
$range = explode('-', $range);
$c_start = intval($range[0]);
$c_end = isset($range[1]) && is_numeric($range[1]) ? intval($range[1]) : $size;
}
// Minor normalization: end bytes can not be larger than $end.
$c_end = $c_end > $end ? $end : $c_end;
// If the requested range is not valid, respond with a 416.
if ($c_start > $c_end || $c_start > $end || $c_end > $end) {
header('HTTP/1.1 416 Requested Range Not Satisfiable');
header("Content-Range: bytes {$start}-{$end}/{$size}");
exit;
}
$start = $c_start;
$end = $c_end;
$length = $end - $start + 1;
fseek($fp, $start);
// The ranged request is valid and will be performed, respond with a 206.
header('HTTP/1.1 206 Partial Content');
header("Content-Range: bytes {$start}-{$end}/{$size}");
}
header("Content-Length: {$length}");
// Start buffered download. Prevent reading too far for a ranged request.
$buffer = 1024 * 8;
while (!feof($fp) && ($p = ftell($fp)) <= $end) {
if ($p + $buffer > $end) {
$buffer = $end - $p + 1;
}
set_time_limit(0);
// Reset time limit for big files.
echo fread($fp, $buffer);
flush();
// Free up memory, to prevent triggering PHP's memory limit.
}
fclose($fp);
}