问题 如何缓存将图像返回到asp.net mvc中的视图的动作方法的输出?


我已经阅读了很多关于缓存的帖子,但其中没有一篇确实符合我的需求。在我的mvc 3应用程序中,我有一个动作方法GetImage(),它返回一个图像类型的文件。然后我在视图中使用此方法来显示图像:

<img width="75" height="75" src="@Url.Action("GetImage", "Store", new {productId = item.ProductId})"/>

我想在服务器上缓存图像。所以,我已经尝试过:

1)使用OutputCacheAttribute:

    [HttpGet, OutputCache(Duration = 10, VaryByParam = "productId", Location = OutputCacheLocation.Server, NoStore = true)]
    public FileContentResult GetImage(int productId)
    {
        var p = _productRepository.GetProduct(productId);
        if (p != null)
        {
            if (System.IO.File.Exists(GetFullProductImagePath(productId)))
            {
                var image = Image.FromFile(GetFullProductImagePath(productId));
                return File(GetFileContents(image), "image/jpeg");
            }
        }
        var defaultPath = AppDomain.CurrentDomain.BaseDirectory +
                             ConfigurationManager.AppSettings["default-images-directory"];

        var defaultImage = Image.FromFile(Path.Combine(defaultPath, "DefaultProductImage.jpg"));
        return File(GetFileContents(defaultImage), "image/jpeg");
    }

图像没有缓存(我得到状态:200 OK)

2)在GetImage()方法中使用以下Response.Cache方法:

    public FileContentResult GetImage(int productId)
    {
        Response.Cache.SetCacheability(HttpCacheability.Public);
        Response.Cache.SetMaxAge(new TimeSpan(0, 0, 0, 10));
        Response.Cache.SetExpires(DateTime.Now.Add(new TimeSpan(0, 0, 0, 10)));
        Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");        
        // other code is the same
    }

图像未缓存

3)我得到:304 Not Modified,但GetImage()方法什么都不返回(空图像)

    public FileContentResult GetImage(int productId)
    {
        Response.StatusCode = 304;
        Response.StatusDescription = "Not Modified";
        Response.AddHeader("Content-Length", "0");     
        // other code is the same
    }

问题:如何在服务器上缓存此操作方法的输出?


1915
2018-02-08 09:27


起源



答案:


试试这样:

[HttpGet]
[OutputCache(
    Duration = 10, 
    VaryByParam = "productId", 
    Location = OutputCacheLocation.ServerAndClient)]
public ActionResult GetImage(string productId)
{
    ...
}

需要注意的事项:使用 OutputCacheLocation.ServerAndClient 并且摆脱了 NoStore = true


13
2018-02-08 09:58



谢谢,它完美无缺!但我不明白:我不能单独将图像缓存在服务器或客户端上? - Aleksei Chepovoi
但是当您仅在服务器上缓存图像时,此服务器就是 总是 击中。客户端没有缓存图像,也没有它的副本。您认为客户会从哪里获得此图片?这就是你获得200状态代码的原因。不同之处在于,您不会在服务器上调用昂贵的控制器操作,而是将图像从缓存直接提供给客户端。 - Darin Dimitrov
我需要VaryByParam =“ProductId”吗?好像它不影响结果?而且,正如我所知,“ServerAndClient”意味着所有用户都将获得相同的缓存图像? - Aleksei Chepovoi
你需要的 VaryByParam 如果你想要缓存的变化 productId 参数。缓存存储在服务器和每个客户端上,因此每个客户端都将获得相同的图像(由...改变) productId 参数当然)。 - Darin Dimitrov
如果您不使用VaryByParam参数,则用户将获得所有产品的相同图像。 - Hüseyin Yağlı


答案:


试试这样:

[HttpGet]
[OutputCache(
    Duration = 10, 
    VaryByParam = "productId", 
    Location = OutputCacheLocation.ServerAndClient)]
public ActionResult GetImage(string productId)
{
    ...
}

需要注意的事项:使用 OutputCacheLocation.ServerAndClient 并且摆脱了 NoStore = true


13
2018-02-08 09:58



谢谢,它完美无缺!但我不明白:我不能单独将图像缓存在服务器或客户端上? - Aleksei Chepovoi
但是当您仅在服务器上缓存图像时,此服务器就是 总是 击中。客户端没有缓存图像,也没有它的副本。您认为客户会从哪里获得此图片?这就是你获得200状态代码的原因。不同之处在于,您不会在服务器上调用昂贵的控制器操作,而是将图像从缓存直接提供给客户端。 - Darin Dimitrov
我需要VaryByParam =“ProductId”吗?好像它不影响结果?而且,正如我所知,“ServerAndClient”意味着所有用户都将获得相同的缓存图像? - Aleksei Chepovoi
你需要的 VaryByParam 如果你想要缓存的变化 productId 参数。缓存存储在服务器和每个客户端上,因此每个客户端都将获得相同的图像(由...改变) productId 参数当然)。 - Darin Dimitrov
如果您不使用VaryByParam参数,则用户将获得所有产品的相同图像。 - Hüseyin Yağlı