source: extensions/PiwigoLib/PiwigoWpf/Services/ImageCacheManager.cs @ 11922

Last change on this file since 11922 was 11922, checked in by bayral, 9 years ago

Async image thumbail retriving

File size: 10.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Com.Piwigo.Wpf.DTO;
6using System.Threading;
7using System.IO;
8using System.Net;
9using System.Drawing;
10using Com.Piwigo.Wpf.Helper;
11
12namespace Com.Piwigo.Wpf.Service
13{
14    public class ImageCacheManager
15    {
16        #region WPF Converter
17        static readonly ImageUrlCachedConverter _imageUrlCachedConverter = new ImageUrlCachedConverter();
18
19        public static ImageUrlCachedConverter ImageUrlCachedConverter
20        {
21            get
22            {
23                return _imageUrlCachedConverter;
24            }
25        }
26
27        public static String GetDefaultImage()
28        {
29            return ("pack://application:,,,/Pictures/Globe.png");
30        }
31
32        #endregion WPF Converter
33
34        #region Singleton
35        static readonly ImageCacheManagerBase _instance = new ImageCacheManagerBase();
36
37        // Explicit static constructor to tell C# compiler
38        // not to mark type as beforefieldinit
39        static ImageCacheManager()
40        {
41            Int32 a, b;
42            ThreadPool.GetMaxThreads(out a, out b);
43            if (a>20) a = 20;
44            ThreadPool.SetMaxThreads(a, b);
45        }
46
47        public static ImageCacheManagerBase Instance
48        {
49            get
50            {
51                return _instance;
52            }
53        }
54        #endregion Singleton
55
56        #region singleton base class
57        public class ImageCacheManagerBase : IDisposable
58        {
59            #region DTO
60            // local DTO
61            internal class CategoryDictionnaryItem
62            {
63                internal DirectoryInfo BasePath;
64                internal String CategorieId;
65            };
66
67            internal class CategoryDictionnary : SortedDictionary<String, CategoryDictionnaryItem> { };
68
69            internal class ServerDictionnaryItem
70            {
71                internal DirectoryInfo BasePath;
72                internal CategoryDictionnary Categories;
73                internal Uri ServeurUrl;
74            };
75
76            internal class ServerDictionnary : SortedDictionary<String, ServerDictionnaryItem> { };
77
78            internal static DirectoryInfo AppCachedDataDirectory = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),"PiwigoWpf", "cache"));
79
80            internal Object _lock = new Object();
81            internal ServerDictionnary _aServerDictionnary;
82            internal ServerDictionnaryItem _currentServer;
83            internal CategoryDictionnaryItem _currentCategory;
84
85            #endregion DTO
86
87            #region local helper
88            // local helper
89            static private String BuildServerDirCache(String serveurUri)
90            {
91                String ServerDirCache = Path.Combine(AppCachedDataDirectory.FullName, serveurUri.Replace("http://", "_").Replace("/", "_"));
92                System.Diagnostics.Debug.Print(ServerDirCache);
93
94                return ServerDirCache;
95            }
96           
97            static private String BuildCategoryDirCache(ServerDictionnaryItem server, String CatgeoryId)
98            {
99                String CategoryDirCache = String.Empty;
100                if (server != null)
101                {
102                    CategoryDirCache = Path.Combine(server.BasePath.FullName, CatgeoryId.Replace("/", "_")); 
103                }
104                else
105                {
106                    throw new ApplicationException ("Current server not set before using category");
107                }
108
109                return CategoryDirCache;
110            }
111
112            static private ServerDictionnary BuildServerDictionnaryFromCache()
113            {
114                ServerDictionnary retLstServerDictionnary = new ServerDictionnary();
115
116                if (AppCachedDataDirectory.Exists)
117                {
118                    foreach (DirectoryInfo Dir in AppCachedDataDirectory.GetDirectories())
119                    {
120                        FileInfo xmlData = new FileInfo(Path.Combine(Dir.FullName, "serverdictionnaryitem.xml"));
121                        if (xmlData.Exists)
122                        {
123                            ServerDictionnaryItem item = XMLHelper<ServerDictionnaryItem>.DeserializeObjectFromFile(xmlData);
124                            retLstServerDictionnary.Add(item.ServeurUrl.ToString(), item);
125                        }
126                    }
127                }
128
129                return retLstServerDictionnary;
130            }
131
132            static void WriteServerDictionnaryToDisk(ServerDictionnary dcServer)
133            {
134                foreach (ServerDictionnaryItem Item in dcServer.Values)
135                {
136                    FileInfo xmlData = new FileInfo(Path.Combine(Item.BasePath.FullName, "serverdictionnaryitem.xml"));
137                    XMLHelper<ServerDictionnaryItem>.SerializeToXMLFile(Item, xmlData);
138                }
139            }
140            #endregion local helper
141
142            public void UnsetCurrentServer()
143            { 
144                _currentCategory = null;
145                _currentServer = null;
146            }
147
148            public void SetCurrentServer(String serveurUri)
149            {
150                String currentserverDir = BuildServerDirCache(serveurUri);
151                lock (_lock)
152                {
153                    // load data from disk on first access
154                    if (_aServerDictionnary == null)
155                    {
156                        _aServerDictionnary = BuildServerDictionnaryFromCache();
157                    }
158
159                    if (_aServerDictionnary.ContainsKey(serveurUri))
160                    {
161                        _currentServer = _aServerDictionnary[serveurUri];
162                    }
163                    else
164                    {
165                        ServerDictionnaryItem server = new ServerDictionnaryItem();
166                        server.ServeurUrl = new Uri(serveurUri);
167                        server.BasePath = new DirectoryInfo(currentserverDir);
168                        server.Categories = new CategoryDictionnary();
169                        _aServerDictionnary.Add(serveurUri, server);
170                        _currentServer = server;
171                    }
172
173                    if (!Directory.Exists(currentserverDir))
174                    {
175                        //Create it
176                        Directory.CreateDirectory(currentserverDir);
177                        _currentServer.Categories.Clear();
178                    }
179                }
180            }
181
182            public void SetCurrentCategory(String CategorieId)
183            {
184                if (_currentServer != null)
185                {
186                    lock (_lock)
187                    {
188                        String currentsCategoryDir = BuildCategoryDirCache(_currentServer, CategorieId);
189                        if (_currentServer.Categories.ContainsKey(CategorieId))
190                        {
191                            _currentCategory = _currentServer.Categories[CategorieId];
192                        }
193                        else
194                        {
195                            CategoryDictionnaryItem category = new CategoryDictionnaryItem();
196                            category.BasePath = new DirectoryInfo(currentsCategoryDir);
197                            category.CategorieId = CategorieId;
198                            _currentServer.Categories.Add(CategorieId, category);
199                            _currentCategory = category;
200                        }
201
202                        if (!Directory.Exists(currentsCategoryDir))
203                        {
204                            //Create it
205                            Directory.CreateDirectory(currentsCategoryDir);
206                        }
207                    }
208                }
209                else
210                {
211                    throw new ApplicationException("Current server not set before using category");
212                }
213            }
214
215            public String GetImageFilename(PwgImageWPF aImageWPF)
216                {
217                    String retImgSrc = String.Empty;
218                    if (aImageWPF == null)
219                    {
220                        return retImgSrc;
221                    }
222
223                    if (_currentCategory != null)
224                    {
225                        String localFile = Path.Combine(_currentCategory.BasePath.FullName, String.Format("{0}-{1}", aImageWPF.Id, aImageWPF.File));
226
227                        if (!File.Exists(localFile))
228                        {
229                            retImgSrc = GetDefaultImage();
230
231                            ThreadPool.QueueUserWorkItem((WaitCallback)delegate
232                            {
233                                WebRequest request = HttpWebRequest.Create(aImageWPF.UrlElement);
234                                WebResponse response = request.GetResponse();
235
236                                //check the content type to assert that the file in the uri is an image
237                                if (!response.ContentType.StartsWith("image"))
238                                {
239                                    throw new FileFormatException(aImageWPF.UrlElement, String.Format("Uri passed to ImageCacher does not return an image. Content is of type {0}.", response.ContentType));
240                                }
241
242                                //load the image from the stream
243                                Image image = Image.FromStream(response.GetResponseStream());
244
245                                //save it
246                                image.Save(localFile);
247
248                                aImageWPF.ImgSource = localFile; 
249                            });
250                        }
251                        else
252                        {
253                            retImgSrc = localFile; 
254                        }
255                        return retImgSrc;
256                    }
257                    else
258                    {
259                        throw new ApplicationException("Current category not set before using image cache.");
260                    }
261                }
262
263            public void Dispose()
264            {
265                if (_aServerDictionnary != null)
266                {
267                    WriteServerDictionnaryToDisk(_aServerDictionnary);
268                }
269            }
270        }
271
272        #endregion singleton base class
273}
274
275}
Note: See TracBrowser for help on using the repository browser.