프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / DownloadManager / PageStorage.cs @ 6a19b48d

이력 | 보기 | 이력해설 | 다운로드 (9.82 KB)

1
using System;
2
using System.Collections.Concurrent;
3
using System.Collections.Generic;
4
using System.ComponentModel;
5
using System.Linq;
6
using System.Text;
7
using System.Threading.Tasks;
8

    
9
namespace KCOM.PageManager
10
{
11
    public class PageStorage
12
    {
13
        public event EventHandler<PageLoadCompletedEventArgs> PageLoadCompleted;
14

    
15
        private const int DEFUALT_TALK_PAGE_COUNT = 10;
16

    
17
        List<int> WorkItems = new List<int>();
18
        ConcurrentBag<PageItem> fileItems = new ConcurrentBag<PageItem>();
19
        BackgroundWorker backgroundWorker;
20
        
21
        string _localStorage;
22
        string _fileExt;
23
        string _BaseUri;
24
        int _TotalPages;
25
        int _TakeCount;
26

    
27
        bool IsWork = false;
28
        bool IsDownload = false;
29

    
30
        public PageStorage(string BaseUri, string localStoragePath, string fileExt, int totalPages, int takeCount = 5)
31
        {
32
            try
33
            {
34
                backgroundWorker = new BackgroundWorker { WorkerSupportsCancellation = true, WorkerReportsProgress = true };
35
                backgroundWorker.DoWork += BackgroundWorker_DoWork;
36
                backgroundWorker.ProgressChanged += BackgroundWorker_ProgressChanged;
37
                _fileExt = fileExt;
38
                _BaseUri = BaseUri;
39
                _localStorage = localStoragePath;
40
                _TotalPages = totalPages;
41
                _TakeCount = takeCount;
42

    
43
                System.IO.Directory.CreateDirectory(_localStorage);
44

    
45
                //backgroundWorker.RunWorkerAsync(new int[] { 1, 10 });
46
            }
47
            catch (Exception ex)
48
            {
49
                throw new Exception("PageStorage", ex);
50
            }
51
        }
52

    
53
        private void BackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
54
        {
55
            System.Diagnostics.Debug.WriteLine(_fileExt + ":" + e.ProgressPercentage.ToString() + "%");
56
        }
57

    
58
        private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
59
        {
60
             DownloadWork();
61
        }
62

    
63
        private void DownloadWork()
64
        { 
65
            while (WorkItems.Count > 0)
66
            {
67
                if (!IsDownload)
68
                {
69
                    int item = -1;
70
                    try
71
                    {
72

    
73
                        if (WorkItems.TryFrist(true, out item))
74
                        {
75
                            var result = DownloadPageAsync(item, null);
76
                        }
77
                    }
78
                    catch (Exception ex)
79
                    {
80
                        System.Diagnostics.Debug.WriteLine(ex.ToString());
81
                    }
82
                }
83

    
84
                System.Threading.Thread.Sleep(100);
85

    
86
            }
87

    
88
            IsWork = false;
89
        }
90

    
91
        public async void DownloadWorkAsync(int startPage, int TakeCount)
92
        {
93
            if (0 < _TakeCount && startPage < _TotalPages)
94
            {
95
                int takecount = _TakeCount;
96

    
97
                if (_TotalPages < startPage + takecount)
98
                {
99
                    takecount = _TotalPages - startPage;
100
                    _TakeCount = 0;
101
                }
102

    
103
                WorkItems.AddRange(Enumerable.Range(startPage, TakeCount - 1));
104
            }
105

    
106
            if (!IsWork && WorkItems.Count() > 0)
107
            {
108
                IsWork = true;
109
                await Task.Run(() => DownloadWork());
110
            }
111
            //if (!backgroundWorker.IsBusy && WorkItems.Count() > 0)
112
            //{
113
            //    backgroundWorker.RunWorkerAsync();
114
            //}
115
        }
116

    
117
        public  void DownloadWork(int startPage, int TakeCount)
118
        {
119
            if (0 < _TakeCount && startPage <= _TotalPages)
120
            {
121
                WorkItems.AddRange(Enumerable.Range(startPage, _TotalPages));
122
            }
123

    
124
            if (!IsWork && WorkItems.Count() > 0)
125
            {
126
                IsWork = true;
127
                DownloadWork();
128
            }
129
        }
130

    
131
        public async Task<Uri> GetPageUriAsync(System.Threading.CancellationToken? cts, int PageNo, bool IsRestart = false)
132
        {
133
            IsDownload = true;
134

    
135
            Uri result = null;
136

    
137
            try
138
            {
139
                System.Diagnostics.Debug.WriteLine("GetPageAsync");
140

    
141
                var pageItem = await DownloadPageAsync(PageNo, cts);
142

    
143
                // 다음 페이지가 미리 다운로드 되도록 추가
144
                if (pageItem != null && 0 < _TakeCount && PageNo + 1 < _TotalPages)
145
                {
146
                    int takecount = _TakeCount;
147

    
148
                    if (_TotalPages < PageNo + 1 + takecount)
149
                    {
150
                        takecount = _TotalPages - PageNo + 1;
151
                    }
152

    
153
                    DownloadWorkAsync(PageNo + 1, takecount);
154
                    //var takePageNoList = Enumerable.Range(PageNo + 1, _TakeCount);
155
                }
156

    
157
                result = pageItem.LocalUri;
158
            }
159
            catch (Exception ex)
160
            {
161
                if (cts != null)
162
                {
163
                    if (cts.Value.IsCancellationRequested)
164
                    {
165
                        return result;
166
                    }
167
                }
168

    
169
                if (!IsRestart)
170
                {
171
                    await Task.Delay(100);
172

    
173
                    result = await GetPageUriAsync(cts, PageNo, true);
174
                }
175
                //throw new Exception("GetPageAsync(string BasePageUri,int PageNo)", ex);
176
            }
177
            finally
178
            {
179
                IsDownload = false;
180
            }
181

    
182
            return result;
183
        }
184

    
185
        public async Task<PageItem> DownloadPageAsync(int PageNo, System.Threading.CancellationToken? cts)
186
        {
187
            IsDownload = true;
188
            PageItem result = new PageItem { PageNo = PageNo };
189

    
190
            try
191
            {
192
                var page = fileItems.Where(x => x.PageNo == PageNo).ToList();
193

    
194
                if (page.Count > 0)
195
                {
196
                    System.Diagnostics.Debug.WriteLine("DownloadPageAsync fileItems");
197

    
198
                    result = page.First();
199

    
200
                    /// 파일 체크 후 없으면 다시 다운로드
201
                    if (!System.IO.File.Exists(result.LocalFilePath))
202
                    {
203
                        //fileItems.(result);
204

    
205
                        result = await DownloadPageAsync(PageNo, cts);
206
                    }
207
                }
208
                else
209
                {
210

    
211
                    System.Diagnostics.Debug.WriteLine("DownloadPageAsync down");
212

    
213
                    string downloadFilePath = System.IO.Path.Combine(_localStorage, PageNo.ToString() + "." + _fileExt);
214

    
215
                    Uri originalUri = new Uri(_BaseUri.Replace("{PageNo}", PageNo.ToString()));
216

    
217
                    result = new PageItem
218
                    {
219
                        PageNo = PageNo,
220
                        OriginalUri = originalUri,
221
                        LocalUri = new Uri(downloadFilePath, UriKind.Absolute),
222
                        LocalFilePath = downloadFilePath
223
                    };
224

    
225
                    if (fileItems.Where(x => x.PageNo == PageNo).Count() == 0)
226
                    {
227
                        fileItems.Add(result);
228
                    }
229

    
230
                    using (System.Net.WebClient client = new System.Net.WebClient())
231
                    {
232
                        client.UseDefaultCredentials = true;
233
                        //client.Headers.Add("user-agent", "Your User-Agent");
234
                        System.Net.IWebProxy webProxy = client.Proxy;
235

    
236
                        if (webProxy != null)
237
                        {
238
                            // Use the default credentials of the logged on user.
239
                            webProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
240
                        }
241

    
242
                        if (cts != null)
243
                        {
244
                            client.DownloadProgressChanged += (snd, ect) =>
245
                            {
246
                                IsDownload = client.IsBusy;
247

    
248
                                if (cts.Value.IsCancellationRequested)
249
                                {
250
                                    client.CancelAsync();
251
                                }
252
                            };
253
                        }
254

    
255
                        client.DownloadFileCompleted += (snd, evt) =>
256
                        {
257
                            result.IsDownLoad = true;
258

    
259
                            bool isLast = false;
260
                            
261
                            if(result.PageNo == _TotalPages)
262
                            {
263
                                isLast = true;
264
                            }
265

    
266
                            PageLoadCompleted?.Invoke(this, new PageLoadCompletedEventArgs(result, isLast));
267
                            System.Diagnostics.Debug.WriteLine("Download : " + downloadFilePath);
268
                        };
269

    
270
                        await client.DownloadFileTaskAsync(originalUri, downloadFilePath);
271

    
272
                    }
273

    
274
                    //}
275
                    //System.Diagnostics.Debug.WriteLine("Download : " + result.LocalFilePath);
276
                }
277
            }
278
            catch (Exception ex)
279
            {
280
                throw new Exception("DownloadPageAsync : ", ex);
281
            }
282
            finally
283
            {
284
                IsDownload = false;
285
            }
286

    
287
            return result;
288
        }
289

    
290
        public void Clear()
291
        {
292
            try
293
            {
294
                backgroundWorker.CancelAsync();
295
                backgroundWorker.Dispose();
296

    
297
                foreach (var item in fileItems)
298
                {
299
                    System.IO.File.Delete(item.LocalFilePath);
300
                }
301

    
302
                System.IO.Directory.Delete(_localStorage, true);
303
            }
304
            catch (Exception ex)
305
            {
306
                System.Diagnostics.Debug.WriteLine(ex.ToString());
307
            }
308
        }
309
    }
310
}
클립보드 이미지 추가 (최대 크기: 500 MB)