如何在 ASP.NET MVC RC1 中使用 FileResult 返回 304 状态

发布于 2024-07-14 13:06:15 字数 660 浏览 3 评论 0原文

您可能知道,在 ASP.NET MVC 的 RC1 版本中,我们有一个名为 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 还是其他内容?

As you may know we have got a new ActionResult called FileResult in RC1 version of ASP.NET MVC.

Using that, your action methods can return image to browser dynamically. Something like this:

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

In the HTML code, we can use something like this:

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

Since the image is returned dynamically, we need a way to cache the returned stream so that we don't need to read the image again from database. I guess we can do it with something like this, I'm not sure:

Response.StatusCode = 304;

This tells the browser that you already have the image in your cache. I just don't know what to return in my action method after setting StatusCode to 304. Should I return null or something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

指尖上得阳光 2024-07-21 13:06:15

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

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

博客中的代码片段:

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);
}

This blog answered the question for me; http://weblogs.asp.net/jeff/archive/2009/07/01/304-your-images-from-a-database.aspx

Basically, you need to read the request header, compare the last modified dates and return 304 if they match, otherwise return the image (with a 200 status) and set the cache headers appropriately.

Code snippet from the blog:

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);
}
撩发小公举 2024-07-21 13:06:15

不要将 304 与 FileResult 一起使用。 来自规范

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

从你的问题中尚不清楚你想做什么。 服务器不知道浏览器的缓存中有什么。 浏览器决定这一点。 如果您试图告诉浏览器在已经有副本的情况下不要在需要时重新获取图像,请设置响应 缓存控制标头

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

Don't use 304 with FileResult. From the spec:

The 304 response MUST NOT contain a
message-body, and thus is always
terminated by the first empty line
after the header fields.

It's not clear what you're trying to do from your question. The server doesn't know what the browser has in its cache. The browser decides that. If you're trying to tell the browser not to re-fetch the image when needed again if it already has a copy, set the response Cache-Control header.

If you need to return 304, use EmptyResult instead.

死开点丶别碍眼 2024-07-21 13:06:15

在较新版本的 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);
}

In newer versions of MVC you'd be better off returning an HttpStatusCodeResult. That way you don't need to set the Response.StatusCode or mess with anything else.

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文