2012-01-31 14 views
25

tarayıcı önbelleği görüntüleri olun.ASP.NET MVC: Bir dosya döner ve sadece bir argüman (id) sahip bir actionmethod sahip eylem

örn.

public ActionResult Icon(long id) 
{ 
    return File(Server.MapPath("~/Content/Images/image" + id + ".png"), "image/png"); 
} 

Ben tarayıcı otomatik olarak bu görüntüyü ben tüm verileri indirmek zorunda değildir dahaki sefere öyle erişim ilk kez önbelleğe almak istiyorum.

Ben yanıtta OutputCacheAttribute gibi noktaları elle ayarlama başlıklarını kullanarak çalıştılar. yani:

[OutputCache(Duration = 360000)] 

veya

Response.Cache.SetCacheability(HttpCacheability.Public); 
Response.Cache.SetExpires(Cache.NoAbsoluteExpiration); 

Ama görüntü hala ben tarayıcı (ı Chrome ve Internet Explorer üzerinde çalışıyorum) üzerinde F5 her vuruşunda yüklenir. (Her seferinde yüklendiğini biliyorum çünkü görüntüyü değiştirirsem tarayıcıda da değişir).

Cache-Control: Kamu, max-yaş = 360000

İçerik-Uzunluk: 39317

İçerik-

Ben HTTP yanıt görünüşte çalışması gereken bazı başlıkları olduğunu görmekteyiz Tür: image/png

Tarih: Sal, 31 Ocak 2012 23:20:57 GMT

geçerlilik tarihi: Sun, 05 Şubat 2012 03:20:56 GMT

Son Güncelleme: Sal, 31 Ocak 2012 23:20:56 GMT

Ama istek başlıklarını bu var:

Pragma: no-cache

bu nasıl yapılacağı hakkında herhangi bir fikir ? Unutulmaması gereken

Çok teşekkürler

cevap

19

ilk şey tarayıcıda önbelleğe oldum bile, Chrome, Safari veya IE F5 (yenile) vurduğunda görüntüleri tekrar talep edilecektir olmasıdır.

yine aşağıda başına, hiçbir içeriğe sahip bir 304 yanıtı döndürmek gerekir bu görüntüyü indirmek gerekmez tarayıcı anlatmak için.

Response.StatusCode = 304; 
Response.StatusDescription = "Not Modified"; 
Response.AddHeader("Content-Length", "0"); 

Yine de, 304 yanıtını döndürmeden önce -düzenlendikten sonra istek üstbilgisini kontrol etmek isteyebilirsiniz. Bu nedenle, görüntü kaynağınızın değiştirilmiş tarihine göre Değiştirilmiş-Sona Erme tarihini kontrol etmeniz gerekir (bu dosyadan mı yoksa veritabanında mı saklansın, vs.). Dosya değişmemişse, 304'ü iade edin, aksi halde görüntü (kaynak) ile geri dönün.İşte

bu işlevi

+2

Çok teşekkürler, aradığım sadece ne. Yine de karmaşık görünüyor, ASP.NET MVC kullanarak bunu yapmanın bir "daha standart" yolu olmamalı? Yanıtı ve son değişikliği alacak ve buna göre ele alacak bir yöntem gibi mi? (Ben de öyle yapardım, ama bunu düşünen ilk insan olduğumu düşünmüyorum). – willvv

+1

Her zaman kendi HttpHandler'ımı kullandım - bu yüzden MVC kullanmaya gerek yok, ancak bu şekilde yapılabileceği anlamına gelmiyor - sadece hangi yolun daha iyi performans gösterdiğinden emin değil misiniz? Http://imageresizing.net/ adresine bakmanızı öneririz. Bu, sizin ve daha fazlası için her şeyi ele alabilen harika bir küçük bileşen! – brodie

+0

Sorun şu ki, resimlerim veritabanında saklanıyor ve harici olarak değiştirilebilir, bu nedenle bir HTTP işleyicisi bir seçenek gibi görünmüyor. – willvv

13

Try (bunlar bir HttpHandler ama aynı ilkeler MVC eylem yöntemine uygulanabilir içindir) uygulanması bazı iyi örneklerdir Bu kod, benim için çalışmaktadır

  HttpContext.Response.Cache.SetCacheability(HttpCacheability.Public); 
      HttpContext.Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0)); 

      Entities.Image objImage = // get your Image form your database 

      string rawIfModifiedSince = HttpContext.Request.Headers.Get("If-Modified-Since"); 
      if (string.IsNullOrEmpty(rawIfModifiedSince)) 
      { 
       // Set Last Modified time 
       HttpContext.Response.Cache.SetLastModified(objImage.ModifiedDate); 
      } 
      else 
      { 
       DateTime ifModifiedSince = DateTime.Parse(rawIfModifiedSince); 


       // HTTP does not provide milliseconds, so remove it from the comparison 
       if (objImage.ModifiedDate.AddMilliseconds(
          -objImage.ModifiedDate.Millisecond) == ifModifiedSince) 
       { 
        // The requested file has not changed 
        HttpContext.Response.StatusCode = 304; 
        return Content(string.Empty); 
       } 
      } 

      return File(objImage.File, objImage.ContentType); 
0

Sadece neleri açığa çıkardığımı anlatabilmek için ve nasıl anlatabileceğime dair bir açıklama ya da daha fazla bilgi istiyorum.

Bu: Response.Cache.SetCacheability (HttpCacheability.Public); Response.Cache.SetExpires (Cache.NoAbsoluteExpiration);

... görüntü denetleyicisi üzerinde kırılma noktasını koymak ... ayıklama ile bu ... testi kanıtlamak ve bunu göreceksiniz ..... aslında cache görüntüleri yapar Bir kez vurulmayacak ... bir kaç kez F5 bile olsa ... ama benim için garip olan şey, 200 cevabın hala geri döndüğü.

Çizgiyi dışarı çıkarın ve kırılma noktanıza tekrar basmaya başladığınızı göreceksiniz.

Soru: 200 yanıt alırsanız, bu görüntünün önbellekten sunucu olduğunu söylemenin doğru yolu nedir?

ve bu IIS ile test edildi

8. ifade yerleşik IIS GD Kuru değildir Görsel stüdyo için ..

1

ben @ user2273400, çalışır gelen çözüm kullandık, bu yüzden komple bir çözüm ilanıyla. ben bunu kullanıyorum

public class FileModel 
{ 
    public byte[] File { get; set; } 
    public FileInfo FileInfo { get; set; } 
    public String ContentType { get; set; } 
} 

nasıl:

using System; 
using System.Web; 
using System.Web.Mvc; 
using CIMETY_WelcomePage.Models; 

namespace CIMETY_WelcomePage.Controllers 
{ 
    public class FileController : Controller 
    { 

     public ActionResult Photo(int userId) 
     { 
      HttpContext.Response.Cache.SetCacheability(HttpCacheability.Public); 
      HttpContext.Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0)); 

      FileModel model = GetUserPhoto(userId); 


      string rawIfModifiedSince = HttpContext.Request.Headers.Get("If-Modified-Since"); 
      if (string.IsNullOrEmpty(rawIfModifiedSince)) 
      { 
       // Set Last Modified time 
       HttpContext.Response.Cache.SetLastModified(model.FileInfo.LastWriteTime); 
      } 
      else 
      { 
       DateTime ifModifiedSince = DateTime.Parse(rawIfModifiedSince); 


       // HTTP does not provide milliseconds, so remove it from the comparison 
       if (TrimMilliseconds(model.FileInfo.LastWriteTime.AddMilliseconds) <= ifModifiedSince) 
       { 
        // The requested file has not changed 
        HttpContext.Response.StatusCode = 304; 
        return Content(string.Empty); 
       } 
      } 

      return File(model.File, model.ContentType); 
     } 

     public FileModel GetUserPhoto(int userId) 
     { 
      string filepath = HttpContext.Current.Server.MapPath("~/Photos/635509890038594486.jpg"); 
      //string filepath = frontAdapter.GetUserPhotoPath(userId); 

      FileModel model = new FileModel(); 
      model.File = System.IO.File.ReadAllBytes(filepath); 
      model.FileInfo = new System.IO.FileInfo(filepath); 
      model.ContentType = MimeMapping.GetMimeMapping(filepath); 

      return model; 
     } 

    private DateTime TrimMilliseconds(DateTime dt) 
    { 
     return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, 0); 
    } 

    } 
} 

Ardından Model sınıfı:

Bu eylem ve geçici bir Yardım yöntemi ile benim denetleyicisi olan

<img src="@Url.Action("Photo", "File", new { userId = 15 })" /> 
-1

Düzenleme: Soruyu yanlış anladım. Çözümüm, tarayıcının sayfadaki sunucudan yeni bir istekte bulunmamasıdır. Kullanıcı F5'e basarsa, tarayıcı önbellek bilgisi hakkında ne yaparsanız yapın, sunucudan veri isteyecektir. Bu durumda çözüm, send an HTTP 304 as in @brodie's answer.


Bu problemi bulduğum en kolay çözüm, OutputCacheAttribute kullanmaktı.

davanızı için, OutputCache özelliğinde daha fazla parametre kullanmalıdır:

[OutputCache(Duration = int.MaxValue, VaryByParam = "id", Location=OutputCacheLocation.Client)] 
public ActionResult Icon(long id) 
{ 
    return File(Server.MapPath("~/Content/Images/image" + id + ".png"), "image/png"); 
} 

VaryByParam parametre kimliği dayalı olarak yapılır önbelleğe yapar.Aksi takdirde, ilk görüntü tüm görüntüler için gönderilecektir. Süre parametresini gereksinimlerinize göre değiştirmeniz gerekir. Konum parametresi, önbelleğe almayı yalnızca tarayıcıda yapar. Konum özelliğini aşağıdaki değerlerden birine ayarlayabilirsiniz: Herhangi biri, İstemci, Aşağı Akım, Sunucu, Yok, SunucuAndClient. Varsayılan olarak, Konum özelliği, Any değerine sahiptir.

ayrıntılı bilgi için okuyun:

http://www.asp.net/mvc/overview/older-versions-1/controllers-and-routing/improving-performance-with-output-caching-cs

İlgili konular