Symfony Force Download Response splits text files

I created a function for your Symfony application based on this answer: qaru.site/questions/124509 / ...

The function is as follows:

public function getForceDownloadResponse($file_path, $file_name){
    $file_info = finfo_open(FILEINFO_MIME_TYPE);
    $mine_type = finfo_file($file_info, $file_path.$file_name);
    finfo_close($file_info);

    $response = new Response();
    $response->headers->set('Cache-Control', 'private');
    $response->headers->set('Content-type', $mine_type);
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $file_name . '"');
    $response->headers->set('Content-length', filesize($file_path.$file_name));

    $response->sendHeaders();
    $response->setContent(readfile($file_path.$file_name));

    return $response;
}

      

And it all worked out pretty well ... until someone tried to load a text file with it. For some reason, all text files are loaded with the wrong file name. They all follow this pattern: Actual_File_Name-, attachment like this: new_text.txt-, attachment, etc.

After some investigation, I only found one irregularity with text files in general. Somehow the response header fields are duplicated. Where binaries output something like this:

Cache-Control:private
Connection:close
Content-Disposition:attachment; filename="Jellyfish.jpg"
Content-Length:775702
Content-Type:image/jpeg
Date:Mon, 10 Nov 2014 09:14:41 GMT
Server:Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.5.6

      

Any text file will look like this:

Cache-Control:private
Cache-Control:private
Connection:Keep-Alive
Content-Disposition:attachment; filename="full.txt"
Content-Disposition:attachment; filename="full.txt"
Content-Length:15
Content-Type:text/plain; charset=UTF-8
Date:Mon, 10 Nov 2014 09:06:00 GMT
Keep-Alive:timeout=5, max=97
Server:Apache/2.4.7 (Win32) OpenSSL/1.0.1e PHP/5.5.6

      

I suspect the unintended behavior is rooted somewhere for some reason related to the Content Header behavior. But I can’t let life understand me how it happens.

So, if anyone knows more about how they are created, which might make them behave like this, or even solve the problem directly, any help would be greatly appreciated.

+3


source to share


1 answer


Finally figured it out. Posting it here in case someone, somewhere has a similar problem and finds it helpful:

So. It turns out the problematic line is this:

$response-sendHeaders()

      

For binaries, this line is critical to make it work. They don't need text files and in fact they will be broken as shown above. I don't know exactly why he behaves like this. But the solution was to just check if the requested file is a text file or not. (with throwing an exception for .html files, but this is more an optional / quirk function of the project and can thus be safely ignored)



This is how the function looks now and how it works:

public function getForceDownloadResponse($file_path, $file_name){
    $file_info = finfo_open(FILEINFO_MIME_TYPE);
    $mime_type = finfo_file($file_info, $file_path.$file_name);
    $text = (substr(finfo_file($file_info, $file_path.$file_name), 0, 4) == 'text') ? 1 : 0;
    finfo_close($file_info);

    $response = new Response();
    $response->headers->set('Cache-Control', 'private');
    $response->headers->set('Content-type', $mime_type);
    $response->headers->set('Content-Disposition', 'attachment; filename="' . $file_name . '"');
    $response->headers->set('Content-length', filesize($file_path.$file_name));

    if(!$text || $mime_type == 'text/html'){
        $response->sendHeaders();
    }

    $response->setContent(readfile($file_path.$file_name));

    return $response;
}

      

Since I still don't know what actually caused the different behaviors, this is not as safe and solid as I would like, but it works fine so far.

0


source







All Articles