我正在尝试对现有 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;
}