HttpWebRequest może po prostu użyć cache IE, więc jeśli wszystkie obrazy będą w tym cache tak, a koszt ponownego pisania pliku (ale nie trzeba go pobrać) jest dopuszczalne, można po prostu zrobić wykorzystanie tego.
Jeśli trzeba obsłużyć się jednak wówczas:
Dane:
string uri; //URI of the image.
DateTime? lastMod; // lastModification date of image previously recorded. Null if not known yet.
string eTag; //eTag of image previously recorded. Null if not known yet.
Będziesz musiał przechowywać je pod koniec tego i odzyskać je ponownie (jeśli nie jest nowy image) na początku.To zależy od ciebie, biorąc pod uwagę, że reszta działa:
var req = (HttpWebRequest)WebRequest.Create(uri);
if(lastMod.HasValue)
req.IfModifiedSince = lastMod.Value;//note: must be UTC, use lastMod.Value.ToUniversalTime() if you store it somewhere that converts to localtime, like SQLServer does.
if(eTag != null)
req.AddHeader("If-None-Match", eTag);
try
{
using(var rsp = (HttpWebResponse)req.GetResponse())
{
lastMod = rsp.LastModified;
if(lastMod.Year == 1)//wasn't sent. We're just going to have to download the whole thing next time to be sure.
lastMod = null;
eTag = rsp.GetResponseHeader("ETag");//will be null if absent.
using(var stm = rsp.GetResponseStream())
{
//your code to save the stream here.
}
}
}
catch(WebException we)
{
var hrsp = we.Response as HttpWebResponse;
if(hrsp != null && hrsp.StatusCode == HttpStatusCode.NotModified)
{
//unfortunately, 304 when dealt with directly (rather than letting
//the IE cache be used automatically), is treated as an error. Which is a bit of
//a nuisance, but manageable. Note that if we weren't doing this manually,
//304s would be disguised to look like 200s to our code.
//update these, because possibly only one of them was the same.
lastMod = hrsp.LastModified;
if(lastMod.Year == 1)//wasn't sent.
lastMod = null;
eTag = hrsp.GetResponseHeader("ETag");//will be null if absent.
}
else //some other exception happened!
throw; //or other handling of your choosing
}
E-znaczniki są bardziej niezawodne niż w ubiegłym modyfikowany gdy realizowane prawidłowo (zauważając sub-sekundowe uchwał w sprawie zmian i odzwierciedlające różne reakcje ze względu na różne Accept- * nagłówki). Niektóre implementacje są jednak błędne (IIS6 na farmie sieciowej bez konkretnej poprawki, Apache z mod-gzip), więc warto wydobyć kod związany z e-tagami i po prostu mijać datę.
Edycja: Jeśli chciałbyś pójść jeszcze dalej w implementacji buforowania HTTP, możesz również zapisać wygasanie i maksymalny wiek (użyj tych ostatnich, jeśli oba są obecne i nie zgadzają się z poprzednim) i pomiń pobieranie całkowicie, jeśli jest wcześniej, niż sugerują te wartości. Zrobiłem to i działa dobrze (miałem pamięć podręczną w pamięci obiektów utworzonych przez XML zwrócony przez różne URI, a jeśli XML był świeży lub nie został zmieniony, ponownie użyłem obiektu), ale może to być nieistotne dla twoich potrzeb (jeśli chcesz być odświeżony, niż sugeruje serwer, lub jeśli zawsze będziesz poza tym oknem).
To może Cię zainteresować: https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching – rboarman
Czy masz kontrolę nad serwerem sieciowym? Jeśli nie, czy obsługuje buforowanie, Etagi, ... podczas serwowania tych obrazów? –
Nie wiem, jak to działałoby za pośrednictwem protokołu HTTP, ale można wypróbować [właściwość FileInfo's CreationTime] (http://msdn.microsoft.com/en-us/library/system.io.filesysteminfo.creationtime.aspx). Powód, dla którego nie jestem pewien, to to, że nie mogę stwierdzić, czy wartość nieruchomości byłaby faktyczną datą utworzenia lub czy byłaby to data, w której byłeś ostatni (jestem trochę nieświadomy tego tematu). Warto się przyjrzeć. – MilkyWayJoe