Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[HttpFoundation] BinaryFileResponse is unable to guess mimetype and always return text/html #47824

Closed
@BaptisteContreras

Description

@BaptisteContreras

Symfony version(s) affected

5.4.13

Description

Since this PR, it is not possible to let the BinaryFileResponse object guess the Content-Type header in the prepare method. The current problem showed up when I updated my project from 5.4.12 to 5.4.13 and this code stopped working:

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class BugController extends AbstractController
{
    /**
     * @Route(path="/bug", name="bug")
     */
    public function bug(): Response
    {
        $pdfPath = sprintf('%s/pdf/%s',  $this->getParameter('kernel.project_dir'), 'demo.pdf'); // I have a pdf folder with a demo.pdf in it

        return new BinaryFileResponse($pdfPath);
    }
}

Instead of having my PDF displayed in the browser (screen 1), I have a strange result (screen 2).

When I looked at the response's headers, I noticed that in 5.4.13 the Content-Type is set to text/html; charset=UTF-8 (Cf screen 2). Unlike in 5.4.12, it is set to application/pdf

How to reproduce

  • symfony new reproduce --version="5.4"
  • Ensure that you have "symfony/http-foundation": "5.4.13"
  • composer require doctrine/annotations
  • composer require symfony/mime
  • php -S 127.0.0.1:8080 -t reproduce/public/
  • Create a new Controller with the following code :
<?php


namespace App\Controller;


use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class BugController extends AbstractController
{
    /**
     * @Route(path="/bug", name="bug")
     */
    public function bug(): Response
    {
        $pdfPath = sprintf('%s/pdf/%s',  $this->getParameter('kernel.project_dir'), 'demo.pdf');

        return new BinaryFileResponse($pdfPath);
    }
}

You should have the same result as on screen 2

If you try the same steps but with "symfony/http-foundation": "5.4.12" it should work as screen 1

Possible Solution

Here is a quick solution that comes up in my mind :

We just need to change the beginning of the BinaryFileResponse's prepare method to check if we are in a case where we can guess the Content Type header, then we call Response::prepare method. Thanks to this we keep this FIX and also the behavior of guessing the Content Type of the file to serve.

class BinaryFileResponse extends Response
{

.....

    /**
     * {@inheritdoc}
     */
    public function prepare(Request $request)
    {
        $isInformativeOrEmpty = $this->isInformational() || $this->isEmpty();

        if (!$isInformativeOrEmpty && !$this->headers->has('Content-Type')) {
            $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream');
        }

        parent::prepare($request);

        if ($isInformativeOrEmpty) {
            $this->maxlen = 0;

            return $this;
        }


    //  We can keep the rest of the method...
   }
}

Additional Context

Screen #1

image

Screen #2

image

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