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

Last change on this file since 11926 was 11926, checked in by bayral, 13 years ago

New step for piwigowpf

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