wil*_*lvv 29 asp.net-mvc caching http
我有一个actionmethod返回一个文件,只有一个参数(一个id).
例如
public ActionResult Icon(long id)
{
return File(Server.MapPath("~/Content/Images/image" + id + ".png"), "image/png");
}
Run Code Online (Sandbox Code Playgroud)
我希望浏览器在我第一次访问它时自动缓存此映像,以便下次不必下载所有数据.
我尝试过使用OutputCacheAttribute之类的东西,并在响应上手动设置标题.即:
[OutputCache(Duration = 360000)]
Run Code Online (Sandbox Code Playgroud)
要么
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetExpires(Cache.NoAbsoluteExpiration);
Run Code Online (Sandbox Code Playgroud)
但是每次我在浏览器上点击F5时,图像仍会加载(我在Chrome和IE上尝试).(我知道每次都会加载它,因为如果我更改了图像,它也会在浏览器中更改).
我看到HTTP响应有一些显然应该工作的标题:
Cache-Control:public,max-age = 360000
内容长度:39317
内容类型:图像/ PNG
日期:2012年1月31日星期二23:20:57 GMT
到期日:2012年2月5日,星期日03:20:56 GMT
最后修改时间:2012年1月31日星期二23:20:56 GMT
但请求标头有这个:
附注:无缓存
有关如何做到这一点的任何想法?
非常感谢
bro*_*die 20
首先要注意的是,当您在Chrome,Safari或IE中点击F5(刷新)时,即使它们已在浏览器中缓存,也会再次请求图像.
要告诉浏览器它不需要再次下载图像,您需要返回没有内容的304响应,如下所示.
Response.StatusCode = 304;
Response.StatusDescription = "Not Modified";
Response.AddHeader("Content-Length", "0");
Run Code Online (Sandbox Code Playgroud)
在返回304响应之前,您需要检查If-Modified-Since请求标头.因此,您需要根据图像资源的修改日期检查If-Modified-Since日期(无论是来自文件还是存储在数据库中等).如果文件未更改,则返回304,否则返回图像(资源).
以下是实现此功能的一些很好的示例(这些是针对HttpHandler的,但是相同的原则可以应用于MVC操作方法)
小智 14
试试这个代码,它对我有用
HttpContext.Response.Cache.SetCacheability(HttpCacheability.Public);
HttpContext.Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0));
Entities.Image objImage = // get your Image form your database
string rawIfModifiedSince = HttpContext.Request.Headers.Get("If-Modified-Since");
if (string.IsNullOrEmpty(rawIfModifiedSince))
{
// Set Last Modified time
HttpContext.Response.Cache.SetLastModified(objImage.ModifiedDate);
}
else
{
DateTime ifModifiedSince = DateTime.Parse(rawIfModifiedSince);
// HTTP does not provide milliseconds, so remove it from the comparison
if (objImage.ModifiedDate.AddMilliseconds(
-objImage.ModifiedDate.Millisecond) == ifModifiedSince)
{
// The requested file has not changed
HttpContext.Response.StatusCode = 304;
return Content(string.Empty);
}
}
return File(objImage.File, objImage.ContentType);
Run Code Online (Sandbox Code Playgroud)