ASP.NET MVC:使浏览器从操作中缓存图像

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操作方法)

  • 非常感谢,正是我所寻找的.它确实看起来有点复杂,不应该有一个"更标准"的方式使用ASP.NET MVC吗?就像一个接收响应和最新修改的方法并相应地处理它?(这就是我要做的,但我不认为我是第一个想到这个的人). (2认同)

小智 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)