【问题标题】:Laravel Headers and Caching in phpLaravel 标头和 php 中的缓存
【发布时间】:2013-08-08 16:46:45
【问题描述】:

我有一个小型图像生成器作为我的 laravel4 应用程序的一部分。生成图像大约需要 700 毫秒,因此我已经开始在我的服务器上缓存生成的结果并将其返回给浏览器,这样可以节省一些时间。

由于图像一旦生成就永远不会改变,我想告诉浏览器在本地缓存图像,我使用以下代码完成了这项工作:

$path = $cacheFolderPath . $cacheFileName;

if (File::exists( $path )){
    $response = Response::make(File::get($path));
    $response->header('Content-Type', 'image/png');
    $response->header('Content-Disposition', 'inline; filename="'.$cacheFileName.'"');
    $response->header('Content-Transfer-Encoding', 'binary');
    $response->header('Cache-Control', 'public, max-age=10800, pre-check=10800');
    $response->header('Pragma', 'public');
    $response->header('Expires', date(DATE_RFC822,strtotime(" 2 day")) );
    $response->header('Last-Modified', date(DATE_RFC822, File::lastModified($path)) );
    $response->header('Content-Length', filesize($path));
    return $response;
}

这会将带有状态代码200 OK 的图像发送到具有以下标题的浏览器:

Cache-Control:max-age=10800, pre-check=10800, public
Connection:Keep-Alive
Content-Disposition:inline; filename="pie_0_normal.png"
Content-Length:2129
Content-Transfer-Encoding:binary
Content-Type:image/png
Date:Wed, 07 Aug 2013 10:29:20 GMT
Expires:Fri, 09 Aug 13 10:29:20 +0000
Keep-Alive:timeout=5, max=93
Last-Modified:Wed, 07 Aug 13 10:14:42 +0000
Pragma:public
Server:Apache/2.4.3 (Win32) OpenSSL/1.0.1c PHP/5.4.7
Set-Cookie:laravel_session=767487mhf6j2btv3k01vu56174; expires=Wed, 07-Aug-2013 12:29:20 GMT; path=/; httponly
X-Powered-By:PHP/5.4.7

我的问题是我的浏览器(chrome,未在其他浏览器中测试)仍然拒绝简单地抓取本地缓存版本,而是再次访问服务器。

我花了大约半个小时寻找有关此主题的其他问题,所有这些问题都给了我答案,我已将这些答案纳入上述代码中。所以虽然我知道有类似的问题,但这个问题是上述源代码所独有的。

我的问题是,我做错了什么会导致浏览器不缓存文件?

【问题讨论】:

    标签: php http-headers laravel laravel-4 http-caching


    【解决方案1】:

    另一种方法是检查“If-Modified-Since”请求标头,因为它仅在浏览器已有文件时才会出现。

    如果它存在,那么您知道该文件已经创建并且可以通过链接响应,否则运行上面的代码。像这样的...

    // check if the client validating cache and if it is current
    if ( isset( $headers['If-Modified-Since'] ) && ( strtotime( $headers['If-Modified-Since'] ) == filemtime( $image->get_full_path() ) ) ) {
    
        // cache IS current, respond 304
        header( 'Last-Modified: ' . $image->get_last_modified(), true, 304 );
    
    } else {
    
        // not cached or client cache is older than server, respond 200 and output
    
        header( 'Last-Modified: ' . $image->get_last_modified(), true, 200 );
        header( 'Content-Length: ' . $image->get_filesize() );
        header( 'Cache-Control: max-age=' . $image->get_expires() );
        header( 'Expires: '. gmdate('D, d M Y H:i:s \G\M\T', time() + $image->get_expires() ) );
        header( 'Content-Type: image/jpeg');
    
        print file_get_contents( $image->get_full_path() ); 
    }
    

    【讨论】:

    • 感谢您的回复,我今天将尝试一下,看看它是否能解决问题。听起来好像应该:)
    【解决方案2】:

    您似乎仍在告诉 Laravel 下载资产并将响应作为下载提供,您可以提供 Cache-Control 标头,但这并不重要,因为每次图像被重新生成时已加载。

    我自己也遇到了类似的问题,并发现提供图像的最佳方法是将静态函数注入到我的视图中,例如 ImageController:fetchImage($image)。

    然后该方法将检查本地文件夹以查看文件是否存在,然后它只会返回图像的位置,例如:/img/1332.jpg... 如果文件不存在,它将创建图像,将其保存到 img 文件夹,然后返回位置。

    这避免了 laravel 在每次请求图像时都必须提供一个全新的(未缓存的)响应作为下载,而是指示浏览器加载已经缓存的资源。

    这在我的情况下是有效的......

        if (App::environment('local'))
        {
           return 'http://placehold.it/150x150';
        }
    
    
        $target_file = 'img_cache/'. $release_id .'.jpg';
    
        if (file_exists($target_file)) return '/'.$target_file;
        else
        {
            $release = DB::(get release location on another server from db);
            if(!$release)
                return 'http://placehold.it/150x150';
    
            $imageString = file_get_contents("http://pomed.promoonly.com/".$release[0]->image_src);
    
            file_put_contents($target_file, $imageString);
    
            return '/'.$target_file;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-29
      • 1970-01-01
      • 2013-09-28
      相关资源
      最近更新 更多