Description
\Symfony\Component\HttpFoundation\BinaryFileResponse::prepare()
sets the Content-Length
header based on a simple getSize()
for the file on disk. However, if the file passes through a stream filter that changes its file size, the result is that the file is delivered with the wrong header value, causing it to fail to display properly in most browsers. I discovered this while implementing an encryption layer, because it stores my files encrypted on disk and decrypts them on-the-fly for delivery. I'm able to fix the problem in BinaryFileResponse
, like so:
--- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
+++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php
@@ -186,7 +186,11 @@ class BinaryFileResponse extends Response
*/
public function prepare(Request $request)
{
- $this->headers->set('Content-Length', $this->file->getSize());
+ ob_start();
+ $size = readfile($this->getPathname());
+ ob_end_clean();
+
+ $this->headers->set('Content-Length', $size);
if (!$this->headers->has('Accept-Ranges')) {
// Only accept ranges on safe HTTP methods
The problem could probably be solved in other places, too--like \Symfony\Component\HttpFoundation\File\File::getSize()
--depending on the domain model. (e.g., if File
should be thought of as truly representing the file on disk, it may be a pollution of the concept to modify it to compensate for streaming behavior.)