using System; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Text; using System.Security.Cryptography; using System.Threading; using System.Collections.Generic; using System.IO.IsolatedStorage; using System.IO; using System.Windows.Media.Imaging; using System.Diagnostics; namespace WPImageCaching { internal static class ImageDownloadHelper { private const double EXPIRATIONDAYS = 1.0; //Hilfsmethode zum Laden des Bildes public static void DownloadImage(string url, BitmapImage image, ImageCacheItem item) { string filename = CreateUniqueFilename(url); item.LocalFilename = filename; //Erstellen des Hilfsobjektes zur Übergabe an den asynchronen Aufruf AsyncDataTransfer transfer = new AsyncDataTransfer(); transfer.Item = item; transfer.Image = image; //Erstellen der Abfrage var wc = (HttpWebRequest)HttpWebRequest.Create(url); if (item.ImageID != null) { //Prüfen, ob das Bild im Web immer noch aktuell ist wc.Headers["If-None-Match"] = item.ImageID; } transfer.WebRequest = wc; wc.BeginGetResponse(RequestCallback, transfer); } private static void RequestCallback(IAsyncResult result) { //War die Abfrage erfolgreich if (!result.IsCompleted) { return; } //Herstellen des Hilfsobjektes AsyncDataTransfer transfer = (AsyncDataTransfer)result.AsyncState; try { var response = (HttpWebResponse)transfer.WebRequest.EndGetResponse(result); string newKey = transfer.WebRequest.RequestUri.ToString(); //Bild wurde nicht geändert seit dem letzten Aufruf if (response.StatusCode == HttpStatusCode.NotModified) { if (ImageCache.imageCache.ContainsKey(newKey)) { ImageCache.imageCache[newKey].Expiration = (response.Headers["Expires"] != null) ? DateTime.Parse(response.Headers["Expires"]) : DateTime.Now.AddDays(EXPIRATIONDAYS); //save updated ImageCache.SaveCachedImageInfo(); } Deployment.Current.Dispatcher.BeginInvoke(() => { using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) { lock (ImageCache._lock) { using (IsolatedStorageFileStream fs =isf.OpenFile(transfer.Item.LocalFilename,FileMode.Open)) { transfer.Image.SetSource(fs); } } } }); return; } lock (ImageCache._lock) { if (ImageCache.imageCache.ContainsKey(newKey)) { bool isExpired = (DateTime.Compare(DateTime.Now, ImageCache.imageCache[newKey].Expiration) >= 0); if (!isExpired) { //Setzen des Bildes Deployment.Current.Dispatcher.BeginInvoke( () => { using ( IsolatedStorageFile ifs = IsolatedStorageFile.GetUserStoreForApplication()) { using ( IsolatedStorageFileStream fs = ifs.OpenFile( transfer.Item.LocalFilename, FileMode.Open)) { transfer.Image.SetSource(fs); } } }); return; } else { if (IsolatedStorageFile.GetUserStoreForApplication().FileExists(ImageCache.imageCache[newKey].LocalFilename)) { //remove old image IsolatedStorageFile.GetUserStoreForApplication().DeleteFile(ImageCache.imageCache[newKey].LocalFilename); // ImageCache.imageCache.Remove(newKey); //Speichern der Bildinformationen ImageCache.SaveCachedImageInfo(); } } } //Hat das Bild eine neue ID? if (response.Headers["ETag"] != null) { transfer.Item.ImageID = response.Headers["ETag"]; } else { transfer.Item.ImageID = null; } //Gibt es ein Ablaufdatum? if (response.Headers["Expires"] != null) { transfer.Item.Expiration = DateTime.Parse(response.Headers["Expires"]); } else { transfer.Item.Expiration = DateTime.Now.AddDays(EXPIRATIONDAYS); } var responseStream = response.GetResponseStream(); //Schreiben der Bilddatei using ( var bw = new BinaryWriter( IsolatedStorageFile.GetUserStoreForApplication().CreateFile(transfer.Item.LocalFilename)) ) { byte[] b = new byte[4096]; int read = 0; while ((read = responseStream.Read(b, 0, b.Length)) > 0) { bw.Write(b, 0, read); } bw.Flush(); bw.Close(); } //Setzen des Bildes Deployment.Current.Dispatcher.BeginInvoke( () => { using (IsolatedStorageFile ifs = IsolatedStorageFile.GetUserStoreForApplication()) { using (IsolatedStorageFileStream fs = ifs.OpenFile( transfer.Item.LocalFilename,FileMode.Open)) { transfer.Image.SetSource(fs); } } }); //Hinzufügen der Bildinformationen if (!ImageCache.imageCache.ContainsKey(newKey)) { ImageCache.imageCache.Add(newKey, transfer.Item); //Speichern der Bildinformationen ImageCache.SaveCachedImageInfo(); } } } catch (WebException webException) { } catch (Exception ex) { //Nichts machen, da Bild nicht heruntergeladen werden konnte Debug.WriteLine(ex.ToString()); } } //Erstellt einen eindeutigen Namen für das zu ladende Bild private static string CreateUniqueFilename(string url) { string extension = System.IO.Path.GetExtension(url); byte[] textToHash = Encoding.UTF8.GetBytes(url); SHA1Managed sa = new SHA1Managed(); byte[] hash = sa.ComputeHash(textToHash); return BitConverter.ToString(hash) + extension; } } //Hilfsklasse für den asynchronen Aufruf internal class AsyncDataTransfer { public ManualResetEvent ResetEvent { get; set; } public HttpWebRequest WebRequest { get; set; } public BitmapImage Image { get; set; } public ImageCacheItem Item { get; set; } } }