【问题标题】:How return 304 status with FileResult in ASP.NET MVC RC1如何在 ASP.NET MVC RC1 中使用 FileResult 返回 304 状态
【发布时间】:2009-03-02 12:14:39
【问题描述】:

您可能知道,在 RC1 版本的 ASP.NET MVC 中,我们有一个名为 FileResult 的新 ActionResult

使用它,您的操作方法可以动态地将图像返回给浏览器。像这样的:

public ActionResult DisplayPhoto(int id)
{
   Photo photo = GetPhotoFromDatabase(id);
   return File(photo.Content, photo.ContentType);
}

在 HTML 代码中,我们可以这样使用:

<img src="http://mysite.com/controller/DisplayPhoto/657">

由于图像是动态返回的,我们需要一种方法来缓存返回的流,这样我们就不需要再次从数据库中读取图像。我想我们可以这样做,我不确定:

Response.StatusCode = 304;

这告诉浏览器您的缓存中已经有该图像。在将 StatusCode 设置为 304 后,我只是不知道在我的操作方法中返回什么。我应该返回 null 还是什么?

【问题讨论】:

    标签: asp.net-mvc caching http-status-codes


    【解决方案1】:

    这个博客为我回答了这个问题; http://weblogs.asp.net/jeff/archive/2009/07/01/304-your-images-from-a-database.aspx

    基本上,您需要读取请求标头,比较最后修改的日期,如果匹配则返回 304,否则返回图像(状态为 200)并适当设置缓存标头。

    博客中的代码 sn-p:

    public ActionResult Image(int id)
    {
        var image = _imageRepository.Get(id);
        if (image == null)
            throw new HttpException(404, "Image not found");
        if (!String.IsNullOrEmpty(Request.Headers["If-Modified-Since"]))
        {
            CultureInfo provider = CultureInfo.InvariantCulture;
            var lastMod = DateTime.ParseExact(Request.Headers["If-Modified-Since"], "r", provider).ToLocalTime();
            if (lastMod == image.TimeStamp.AddMilliseconds(-image.TimeStamp.Millisecond))
            {
                Response.StatusCode = 304;
                Response.StatusDescription = "Not Modified";
                return Content(String.Empty);
            }
        }
        var stream = new MemoryStream(image.GetImage());
        Response.Cache.SetCacheability(HttpCacheability.Public);
        Response.Cache.SetLastModified(image.TimeStamp);
        return File(stream, image.MimeType);
    }
    

    【讨论】:

    • 太棒了,这太完美了!不过,我将其更改为不执行 ToLocalTime(),因为我已经将缓存日期存储在 UTC 中。我也return new EmptyResult()。如果您按照引用的博客文章存储 UTC 日期,请记住也要执行 var adjustedTime = DateTime.SpecifyKind(image.TimeStamp, DateKind.Utc)
    • 我喜欢它,这真的很有帮助
    • 当我这样使用时,如果图像发生变化,它仍然需要从浏览器缓存中获取,并且不会访问服务器进行检查。有什么想法吗?请
    【解决方案2】:

    不要在 FileResult 中使用 304。来自the spec

    304 响应不得包含 消息体,因此总是 由第一个空行终止 在标题字段之后。

    从你的问题中不清楚你想做什么。服务器不知道浏览器在它的缓存中有什么。浏览器决定了。如果您试图告诉浏览器不要在需要时重新获取图像(如果它已经有副本),请设置响应 Cache-Control header

    如果需要返回 304,请改用 EmptyResult。

    【讨论】:

    • 在第一个请求中,我将 ETag 属性设置为:HttpContext.Current.Response.Cache.SetETag (someUniqueValue);在随后的请求中,通过阅读 ETag 我知道图像在浏览器的缓存中,因此我必须返回 304
    • 返回 304 时使用 EmptyResult,而不是 FileResult。
    【解决方案3】:

    在较新版本的 MVC 中,您最好返回一个 HttpStatusCodeResult。这样您就不需要设置 Response.StatusCode 或弄乱其他任何东西。

    public ActionResult DisplayPhoto(int id)
    {
        //Your code to check your cache and get the image goes here 
        //...
        if (isChanged)
        {
             return File(photo.Content, photo.ContentType);
        }
        return new HttpStatusCodeResult(HttpStatusCode.NotModified);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      相关资源
      最近更新 更多