merged branch jakzal/2.2-binary-response-fixes (PR #7032)

This PR was merged into the 2.2 branch.

Commits
-------

381bd7e [HttpFoundation] Added support for partial ranges in the BinaryFileResponse.
d9b9145 [HttpFoundation] Fixed byte ranges in the BinaryFileResponse.

Discussion
----------

2.2 binary response fixes

Fixes two problems described in #6961, related to handling requests with a *Range* header:
* BinaryFileResponse returns wrong number of bytes
* BinaryFileResponse incorrectly handles partial ranges

| Q              | A                                        |
|--------------|--------------------------------|
| Bug fix?          | yes |
|New feature? | no |
|BC breaks?    | no |
|Deprecations? |	no |
|Tests pass? | yes |
|Fixed tickets | #6961 |
|License | MIT |
|Doc PR | n/a |
This commit is contained in:
Fabien Potencier 2013-02-09 19:08:46 +01:00
commit f2258e7ec7
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;
$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('IF8');
$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()