Как вернуть статус 304 с FileResult в ASP.NET MVC RC1 - PullRequest
13 голосов
/ 02 марта 2009

Как вы, возможно, знаете, у нас есть новый ActionResult с именем FileResult в RC1-версии ASP.NET MVC.

Используя это, ваши методы действий могут динамически возвращать изображение в браузер. Примерно так:

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. Должен ли я вернуть ноль или что-то еще?

Ответы [ 3 ]

26 голосов
/ 30 мая 2010

Этот блог ответил на вопрос для меня; 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);
}
8 голосов
/ 02 марта 2009

Не используйте 304 с FileResult. От спецификации :

Ответ 304 НЕ ДОЛЖЕН содержать тело сообщения, и, следовательно, всегда завершается первой пустой строкой после полей заголовка.

Непонятно, что вы пытаетесь сделать из своего вопроса. Сервер не знает, что браузер имеет в своем кэше. Браузер решает это. Если вы пытаетесь запретить браузеру повторно загружать изображение при необходимости, если у него уже есть копия, установите ответ Заголовок Cache-Control .

Если вам нужно вернуть 304, используйте вместо этого EmptyResult.

0 голосов
/ 31 марта 2014

В более новых версиях 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...