[HttpFoundation] Added support for partial ranges in the BinaryFileResponse.

Valid ranges include:
* bytes=0-499
* bytes=500-999
* bytes=-500
* bytes=9500-
* bytes=0-0
This commit is contained in:
Jakub Zalas 2013-02-09 16:37:25 +01:00
parent d9b91458f1
commit 381bd7e235
2 changed files with 40 additions and 8 deletions

View File

@ -195,19 +195,27 @@ class BinaryFileResponse extends Response
// Process the range headers.
if (!$request->headers->has('If-Range') || $this->getEtag() == $request->headers->get('If-Range')) {
$range = $request->headers->get('Range');
$fileSize = $this->file->getSize();
list($start, $end) = array_map('intval', explode('-', substr($range, 6), 2)) + array(0);
list($start, $end) = explode('-', substr($range, 6), 2) + array(0);
if ('' !== $end) {
$this->maxlen = $end - $start + 1;
$end = ('' === $end) ? $fileSize - 1 : (int) $end;
if ('' === $start) {
$start = $fileSize - $end;
$end = $fileSize - 1;
} else {
$end = $this->file->getSize() - 1;
$start = (int) $start;
}
$start = max($start, 0);
$end = min($end, $fileSize - 1);
$this->maxlen = $end < $fileSize ? $end - $start + 1 : -1;
$this->offset = $start;
$this->setStatusCode(206);
$this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $this->file->getSize()));
$this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize));
}
}

View File

@ -47,7 +47,10 @@ class BinaryFileResponseTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($response->getContent());
}
public function testRequests()
/**
* @dataProvider provideRanges
*/
public function testRequests($requestRange, $offset, $length, $responseRange)
{
$response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif')->setAutoEtag();
@ -59,14 +62,35 @@ class BinaryFileResponseTest extends \PHPUnit_Framework_TestCase
// prepare a request for a range of the testing file
$request = Request::create('/');
$request->headers->set('If-Range', $etag);
$request->headers->set('Range', 'bytes=1-4');
$request->headers->set('Range', $requestRange);
$this->expectOutputString('IF87');
$file = fopen(__DIR__.'/File/Fixtures/test.gif', 'r');
fseek($file, $offset);
$data = fread($file, $length);
fclose($file);
$this->expectOutputString($data);
$response = clone $response;
$response->prepare($request);
$response->sendContent();
$this->assertEquals(206, $response->getStatusCode());
$this->assertEquals('binary', $response->headers->get('Content-Transfer-Encoding'));
$this->assertEquals($responseRange, $response->headers->get('Content-Range'));
}
public function provideRanges()
{
return array(
array('bytes=1-4', 1, 4, 'bytes 1-4/35'),
array('bytes=-5', 30, 5, 'bytes 30-34/35'),
array('bytes=-35', 0, 35, 'bytes 0-34/35'),
array('bytes=-40', 0, 35, 'bytes 0-34/35'),
array('bytes=30-', 30, 5, 'bytes 30-34/35'),
array('bytes=30-30', 30, 1, 'bytes 30-30/35'),
array('bytes=30-34', 30, 5, 'bytes 30-34/35'),
array('bytes=30-40', 30, 5, 'bytes 30-34/35')
);
}
public function testXSendfile()