0

I use this function to download MP3 files from my server; The files are a few megs large, anywhere between 1 and 10 megs. It works very well however it stops working after a while, it then permanently raises an error (catch section) whenever we use the function, this until I restart the web server. As soon as I restart it, it resumes behaving correctly. The web server is OpenLiteSpeed 1.4.

Kindly advise if I am using the BinaryFileResponse function correctly or not?

function getFile($user_id, $filename)
{
    if (empty($filename)) {
        throw new \InvalidArgumentException('Please provide a valid filename.');
    } else {
        $filepath = "../files/$filename";

        BinaryFileResponse::trustXSendfileTypeHeader();

        try {
            $response = new BinaryFileResponse($filepath);

            $mimeTypes = new MimeTypes();
            $mimeType = $mimeTypes->guessMimeType($filepath);

            $response->headers->set('Content-Type', $mimeType);
            $response->setAutoEtag();
            $response->setContentDisposition(
                ResponseHeaderBag::DISPOSITION_ATTACHMENT,
                $filename
            );
        } catch (FileNotFoundException $exception) {
            $response = new JsonResponse(
                ['Status' => 'Error', 'Message' => DEBUG ? $exception->getMessage() : 'File not found.'],
                Response::HTTP_NOT_FOUND
            );
        }
    }

    return $response;
}
Questionz
  • 45
  • 8
  • This is Symfony, right? Remove the `try/catch` completely so that you can see the full exception. – Chris Haas Nov 10 '21 at 18:44
  • Ok, thanks, so I actually get {"Status":"Error","Message":"The filename and the fallback cannot contain the \u0022\/\u0022 and \u0022\\\u0022 characters."}. I will see how I can split the path and pass individual parameters then – Questionz Nov 10 '21 at 19:25
  • Can you turn that into an answer that you self-accept? – Chris Haas Nov 11 '21 at 01:26
  • I am almost there; from what I understand, the error was related to $filename containing a / when passed as the 2nd param for setContentDisposition. I then just added $filename = basename($filepath); before but now the browser throws an invalid response even though the filename is clean. I checked the $mimeType and it is set correctly to audio/mpeg so this means that it is able to at least find the file in question. The result is the same now with or w/o the try/catch. Any idea? – Questionz Nov 11 '21 at 20:37

1 Answers1

0

I searched for hours but couldn't find an answer so I then decided to take a totally different approach which works fine:

$filename = basename($filepath);

set_time_limit(0);
ini_set('memory_limit', '25M');

while (ob_get_level()) ob_end_clean();
header('Content-Type: audio/mpeg');
header('Content-Disposition:  attachment; filename=' . basename($filepath));
header('Cache-Control: no-cache');
header("Content-Transfer-Encoding: chunked");
ob_flush();
flush();
readfile($filepath);
exit;
Questionz
  • 45
  • 8