mirror of
https://github.com/phpbb/phpbb.git
synced 2025-01-17 14:18:24 +01:00
[ticket/14774] Support partial downloads of attachments
phpBB already had limited support for partial downloads, but only for resuming downloads, disregarding any range ending before EOF. WebKit on iOS and OS X uses partial downloads when fetching media files. Previously, only MP3 attachments could play directly in the browser, reported as a live stream, but with this change, all supported media formats should render as expected. Tested using cURL by verifying that partial downloads give exactly the same results compared to Apache. PHPBB3-14774
This commit is contained in:
parent
65921a7891
commit
d2750b650f
@ -254,11 +254,21 @@ function send_file_to_browser($attachment, $upload_dir, $category)
|
||||
send_status_line(206, 'Partial Content');
|
||||
header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
|
||||
header('Content-Length: ' . $range['bytes_requested']);
|
||||
}
|
||||
|
||||
while (!feof($fp))
|
||||
// First read chunks
|
||||
while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192)
|
||||
{
|
||||
echo fread($fp, 8192);
|
||||
}
|
||||
// Then, read the remainder
|
||||
echo fread($fp, $range['bytes_requested'] % 8192);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo fread($fp, 8192);
|
||||
while (!feof($fp))
|
||||
{
|
||||
echo fread($fp, 8192);
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
@ -529,6 +539,9 @@ function phpbb_find_range_request()
|
||||
*/
|
||||
function phpbb_parse_range_request($request_array, $filesize)
|
||||
{
|
||||
$first_byte_pos = -1;
|
||||
$last_byte_pos = -1;
|
||||
|
||||
// Go through all ranges
|
||||
foreach ($request_array as $range_string)
|
||||
{
|
||||
@ -540,62 +553,61 @@ function phpbb_parse_range_request($request_array, $filesize)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute defaults
|
||||
if ($range[0] === '')
|
||||
{
|
||||
// Return last $range[1] bytes.
|
||||
|
||||
if (!$range[1])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($range[1] >= $filesize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$first_byte_pos = $filesize - (int) $range[1];
|
||||
$last_byte_pos = $filesize - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return bytes from $range[0] to $range[1]
|
||||
|
||||
$first_byte_pos = (int) $range[0];
|
||||
$last_byte_pos = (int) $range[1];
|
||||
|
||||
if ($last_byte_pos && $last_byte_pos < $first_byte_pos)
|
||||
{
|
||||
// The requested range contains 0 bytes.
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($first_byte_pos >= $filesize)
|
||||
{
|
||||
// Requested range not satisfiable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust last-byte-pos if it is absent or greater than the content.
|
||||
if ($range[1] === '' || $last_byte_pos >= $filesize)
|
||||
{
|
||||
$last_byte_pos = $filesize - 1;
|
||||
}
|
||||
$range[0] = 0;
|
||||
}
|
||||
|
||||
// We currently do not support range requests that end before the end of the file
|
||||
if ($last_byte_pos != $filesize - 1)
|
||||
if ($range[1] === '')
|
||||
{
|
||||
$range[1] = $filesize - 1;
|
||||
}
|
||||
|
||||
if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
|
||||
{
|
||||
// We only support contiguous ranges, no multipart stuff :(
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($range[1] && $range[1] < $range[0])
|
||||
{
|
||||
// The requested range contains 0 bytes.
|
||||
continue;
|
||||
}
|
||||
|
||||
return array(
|
||||
'byte_pos_start' => $first_byte_pos,
|
||||
'byte_pos_end' => $last_byte_pos,
|
||||
'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
|
||||
'bytes_total' => $filesize,
|
||||
);
|
||||
// Return bytes from $range[0] to $range[1]
|
||||
if ($first_byte_pos < 0)
|
||||
{
|
||||
$first_byte_pos = (int) $range[0];
|
||||
}
|
||||
|
||||
$last_byte_pos = (int) $range[1];
|
||||
|
||||
if ($first_byte_pos >= $filesize)
|
||||
{
|
||||
// Requested range not satisfiable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust last-byte-pos if it is absent or greater than the content.
|
||||
if ($range[1] === '' || $last_byte_pos >= $filesize)
|
||||
{
|
||||
$last_byte_pos = $filesize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($first_byte_pos < 0 || $last_byte_pos < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'byte_pos_start' => $first_byte_pos,
|
||||
'byte_pos_end' => $last_byte_pos,
|
||||
'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
|
||||
'bytes_total' => $filesize,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,23 +45,71 @@ class phpbb_download_http_byte_range_test extends phpbb_test_case
|
||||
public function parse_range_request_data()
|
||||
{
|
||||
return array(
|
||||
// Does not read until the end of file.
|
||||
// Valid request
|
||||
array(
|
||||
array('3-4'),
|
||||
10,
|
||||
false,
|
||||
array(
|
||||
'byte_pos_start' => 3,
|
||||
'byte_pos_end' => 4,
|
||||
'bytes_requested' => 2,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Valid request, handle second range.
|
||||
// Get the beginning
|
||||
array(
|
||||
array('-5'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 0,
|
||||
'byte_pos_end' => 5,
|
||||
'bytes_requested' => 6,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Get the end
|
||||
array(
|
||||
array('5-'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 5,
|
||||
'byte_pos_end' => 9,
|
||||
'bytes_requested' => 5,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Overlong request
|
||||
array(
|
||||
array('3-20'),
|
||||
10,
|
||||
array(
|
||||
'byte_pos_start' => 3,
|
||||
'byte_pos_end' => 9,
|
||||
'bytes_requested' => 7,
|
||||
'bytes_total' => 10,
|
||||
),
|
||||
),
|
||||
|
||||
// Multiple, contiguous range
|
||||
array(
|
||||
array('10-20', '21-30'),
|
||||
125,
|
||||
array(
|
||||
'byte_pos_start' => 10,
|
||||
'byte_pos_end' => 30,
|
||||
'bytes_requested' => 21,
|
||||
'bytes_total' => 125,
|
||||
)
|
||||
),
|
||||
|
||||
// We don't do multiple, non-contiguous range
|
||||
array(
|
||||
array('0-0', '120-125'),
|
||||
125,
|
||||
array(
|
||||
'byte_pos_start' => 120,
|
||||
'byte_pos_end' => 124,
|
||||
'bytes_requested' => 5,
|
||||
'bytes_total' => 125,
|
||||
)
|
||||
false,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user