Skip to content

BinaryFileResponse sends wrong Content-Length header for files modified by stream wrappers/filters #19738

Closed
@TravisCarden

Description

@TravisCarden

\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.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions