Cannot set Cache-Control in Laravel 4

2019-06-09 00:16发布

问题:

I have written a controller in Laravel 4 to serve up static resources such as image files with some application-level tracking. I don't want people having to constantly hit the web server for each image, though, so I'm trying to set a Cache-Control header. I'm at my wit's end here, it's just plain not working, and I cannot figure out why. Can someone please take a look at the following and tell me what I'm doing wrong?

$headers = array(
    'Content-Type' => 'image/png',
    'Cache-Control' => 'public, max-age=300',
    'Content-Length' => filesize($file),
    'Expires' => date('D, d M Y H:i:s ', time() + 300).'GMT',
);
return Response::stream(function() use ($file) {
    readfile($file); }, 200, $headers);

When I access the file, it works almost perfectly. The image is displayed, and when I go in and inspect the element using Chrome or Firefox, I can see that the Expires header is set correctly (when I change it and force a hard reload, it resets it appropriately). But no matter what I try, the Cache-Control header is always set to "no-cache, private". I've tried using the following, all to no avail:

$headers['Cache-Control'] = 'public, max-age=300'; // Original setting
$headers['cache-control'] = 'public, max-age=300'; // Case-sensitive?
$headers['Cache-Control'] = 'max-age=300';
$headers['Cache-Control'] = 'private, max-age=300';
$headers['Cache-Control'] = 'max-age=300, public';
$headers['Cache-Control'] = 'max-age=300, private';

But like I said, no matter what I set it to, it always returns a response header showing Cache-Control: no-cache, private.

What am I doing wrong? How can I get my image and binary files returned via this controller to cache? Has Laravel 4 for some reason hard-coded the Cache-Control header in all responses?

回答1:

See this issue: https://github.com/symfony/symfony/issues/6530 and this line: https://github.com/symfony/symfony/blob/2.4/src/Symfony/Component/HttpFoundation/StreamedResponse.php#L87

It suggests to use BinaryFileResponse instead. Something like this:

$response = new Symfony\Component\HttpFoundation\BinaryFileResponse($file);
$response->setContentDisposition('inline');
$response->setTtl(300);
return $response;

//Or with setting the headers manually
return  new Symfony\Component\HttpFoundation\BinaryFileResponse($file, 200, $headers, true, 'inline');

Now you can set the Cache-Control headers.

Or using the Response::download() facade:

return Response::download($file)->setTtl(300)->setContentDisposition('inline');
return Response::download($file, null, $headers)->setContentDisposition('inline');