您可能知道我们在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之后,我只是不知道在我的action方法中返回什么。我应该返回null还是什么?
答案 0 :(得分:26)
这个博客为我回答了这个问题; 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);
}
答案 1 :(得分:8)
不要在FileResult中使用304。来自the spec:
304响应不得包含 消息体,因而永远 由第一个空行终止 在标题字段之后。
目前还不清楚你要从你的问题中做些什么。服务器不知道浏览器在其缓存中有什么。浏览器决定这一点。如果您尝试告诉浏览器在需要时再次需要重新获取图片(如果已有副本),请设置回复Cache-Control header。
如果您需要返回304,请改用EmptyResult。
答案 2 :(得分:0)
在较新版本的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);
}