2

我正在尝试对现有 CDN 进行修改。我想要做的是创建一个较短的缓存时间并使用条件 GET 来查看文件是否已更新。

我正在撕毁我的头发,因为即使我设置了最后修改日期并在响应标头中看到它,但在随后的获取请求中,我没有看到返回的 If-Modified-Since 标头。起初我以为是我的本地开发环境,或者是我使用 Fiddler 作为测试代理,所以我部署到了 QA 服务器。但是我在 Firebug 中看到的与我正在做的完全不同。我看到最后修改日期,由于某种原因,它将我的缓存控制设置为私有,并且我已经清除了任何标头输出缓存,并且 IIS 7.5 设置为写入的唯一标头是启用 Http keep-alive,所以所有缓存应该由代码驱动。

这看起来很简单,但是我整天都在添加和删除标题,但没有运气。我检查了 global.asax 和其他任何地方(我没有编写应用程序,所以我一直在寻找任何隐藏的惊喜并且被难住了。下面是当前代码以及请求和响应标头。我将过期设置为 30 秒只是为了测试目的。我查看了几个示例,我认为自己没有做任何不同的事情,但它根本行不通。

响应标头view source
Cache-Control 私有,max-age=30
内容长度 597353
内容类型图片/jpg
日期 2013 年 9 月 3 日星期二 21:33:55 GMT
2013 年 9 月 3 日星期二 21:34:25 GMT
最后修改时间 2013 年 9 月 3 日星期二 21:33:55 GMT
服务器 Microsoft-IIS/7.5
X-AspNet-版本 4.0.30319
X-AspNetMvc-版本 3.0
X-Powered-由 ASP.NET
请求标头view source
接受 text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
接受编码 gzip,放气
Accept-Language en-US,en;q=0.5
连接保持活动
饼干 __utma=1.759556114.1354835397.1377631052.1377732484.36; __utmz=1.1354835397.1.1.utmcsr=(直接)|utmccn=(直接)|utmcmd=(无)
主机 hqat4app1
用户代理 Mozilla/5.0 (Windows NT 6.1; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetLastModified(DateTime.Now);

return new FileContentResult(fileContents, contentType);

相关代码为:

public ActionResult Resize(int id, int size, bool grayscale)
{
    _logger.Debug(() => string.Format("Resize {0} {1} {2}", id, size, grayscale));

    string imageFileName = null;

    if (id > 0)
        using (new UnitOfWorkScope())
            imageFileName = RepositoryFactory.CreateReadOnly<Image>().Where(o => o.Id == id).Select(o => o.FileName).SingleOrDefault();

    CacheImageSize(id, size);

    if (!ImageWasModified(imageFileName))
    {
        Response.Cache.SetExpires(DateTime.Now.AddSeconds(30));
        Response.StatusCode = (int)HttpStatusCode.NotModified;
        Response.Status = "304 Not Modified";
        return new HttpStatusCodeResult((int)HttpStatusCode.NotModified, "Not-Modified");
    }

    byte[] fileContents;
    if (ShouldReturnDefaultImage(imageFileName))
        fileContents = GetDefaultImageContents(size, grayscale);
    else
    {
        bool foundImageFile;
        fileContents = GetImageContents(id, size, grayscale, imageFileName, out foundImageFile);

        if (!foundImageFile)
        {
            // No file found, clear cache, disable output cache
            //ClearOutputAndRuntimeCacheForImage(id, grayscale);
            //Response.DisableKernelCache();
        }
    }
    string contentType = GetBestContentType(imageFileName);

    Response.Cache.SetCacheability(HttpCacheability.Public);
    Response.Cache.SetLastModified(DateTime.Now);

    return new FileContentResult(fileContents, contentType);
}

private bool ImageWasModified(string fileName)
{
    bool foundImageFile;

    string filePath = GetFileOrDefaultPath(fileName, out foundImageFile);

    if (foundImageFile)
    {
        string header = Request.Headers["If-Modified-Since"];

        if(!string.IsNullOrEmpty(header))
        {
            DateTime isModifiedSince;
            if (DateTime.TryParse(header, out isModifiedSince))
            {
                return isModifiedSince < System.IO.File.GetLastWriteTime(filePath);
            }

        }
    }
    return true;
}
4

0 回答 0