File Coverage

blib/lib/Net/Download/Queue/Download.pm
Criterion Covered Total %
statement 24 93 25.8
branch 0 22 0.0
condition 0 14 0.0
subroutine 8 19 42.1
pod 7 7 100.0
total 39 155 25.1


line stmt bran cond sub pod time code
1             =head1 NAME
2            
3             Net::Download::Queue::Download
4            
5             =head1 SYNOPSIS
6            
7            
8             =cut
9            
10            
11            
12            
13            
14             package Net::Download::Queue::Download;
15 1     1   5 use base 'Net::Download::Queue::DBI';
  1         1  
  1         102  
16            
17            
18            
19             our $VERSION = Net::Download::Queue::DBI::VERSION;
20            
21            
22            
23 1     1   6 use strict;
  1         2  
  1         34  
24 1     1   864 use Data::Dumper;
  1         6675  
  1         61  
25            
26 1     1   7 use File::Path;
  1         1  
  1         49  
27 1     1   5 use LWP::UserAgent;
  1         1  
  1         21  
28 1     1   5 use HTTP::Response;
  1         3  
  1         25  
29 1     1   6 use HTTP::Request::Common qw(GET POST);
  1         1  
  1         44  
30 1     1   782 use File::Slurp;
  1         2098988  
  1         1413  
31            
32            
33            
34            
35            
36             =head1 CLASS DBI STUFF
37            
38             =cut
39            
40             __PACKAGE__->set_up_table('download');
41             __PACKAGE__->has_a( download_status_id => 'Net::Download::Queue::DownloadStatus' );
42            
43            
44            
45            
46            
47             =head2 trigger: before_create
48            
49             Set domain and bytesContent.
50            
51             =cut
52             __PACKAGE__->add_trigger(
53             before_create => sub {
54             my $self = shift;
55             $self->domain($self->domainFromUrl($self->url));
56             $self->_attribute_set("bytes_content", $self->bytesContentFromUrl($self->_attrs("url"), $self->_attrs("urlReferer")));
57             }
58             );
59            
60            
61            
62            
63            
64             =head2 retrieve_current
65            
66             Return array with all current downloads.
67            
68             =cut
69             __PACKAGE__->add_constructor(
70             retrieve_current => q{
71             download_status_id in (
72             select status_id from download_status where is_current = 1
73             )
74             });
75            
76            
77            
78            
79            
80             =head2 retrieve_downloading
81            
82             Return array with all downloading downloads.
83            
84             =cut
85             __PACKAGE__->add_constructor(
86             retrieve_downloading => q{
87             download_status_id in (
88             select status_id from download_status where name = 'downloading'
89             )
90             });
91            
92            
93            
94            
95            
96             =head2 sql_bytesSumCurrent->select_val
97            
98             Return total size of current downloads.
99            
100             =cut
101             __PACKAGE__->set_sql(bytesSumCurrent => q{
102             select sum(bytes_content) from __TABLE__ where download_status_id in (
103             select status_id from download_status where is_current = 1
104             )
105             });
106            
107            
108            
109            
110            
111             =head2 sql_bytesSumDownloading->select_val
112            
113             Return total size of downloading downloads.
114            
115             =cut
116             __PACKAGE__->set_sql(bytesSumDownloading => q{
117             select sum(bytes_content) from __TABLE__ where download_status_id in (
118             select status_id from download_status where name = 'downloading'
119             )
120             });
121            
122            
123            
124            
125            
126             =head1 METHODS
127            
128            
129             =head2 setDone()
130            
131             Set the download status to download done ok. Set the bytesDownloaded
132             to bytesContent.
133            
134             Return 1, die on errors.
135            
136             =cut
137             sub setDone {
138 0     0 1   my $self = shift;
139            
140 0           $self->downloadStatusId($self->oDownloadStatus("downloaded: ok"));
141 0           $self->bytesDownloaded( $self->bytesContent );
142 0           $self->update();
143            
144 0           return(1);
145             }
146            
147            
148            
149            
150            
151             =head2 setQueued()
152            
153             Set the download status to queued.
154            
155             Return 1, die on errors.
156            
157             =cut
158             sub setQueued {
159 0     0 1   my $self = shift;
160            
161 0           $self->downloadStatusId($self->oDownloadStatus("queued"));
162 0           $self->update();
163            
164 0           return(1);
165             }
166            
167            
168            
169            
170            
171             =head2 setDownloading()
172            
173             Set the download status to downloading.
174            
175             Return 1, die on errors.
176            
177             =cut
178             sub setDownloading {
179 0     0 1   my $self = shift;
180            
181 0           $self->downloadStatusId($self->oDownloadStatus("downloading"));
182 0           $self->bytesDownloaded(0);
183 0           $self->update();
184            
185 0           return(1);
186             }
187            
188            
189            
190            
191            
192             =head2 setBytesDownloaded($bytesTotal)
193            
194             Set the total number of bytes downloaded in this download.
195            
196             Return 1, die on errors.
197            
198             =cut
199             sub setBytesDownloaded {
200 0     0 1   my $self = shift;
201 0           my ($bytesDownloaded) = @_;
202            
203 0           $self->bytesDownloaded($bytesDownloaded);
204 0           $self->update();
205            
206 0           return(1);
207             }
208            
209            
210            
211            
212            
213             =head2 download([$rsStart], [$rsReceived], [$rsCheckCancel])
214            
215             Attempt to perform download and set the status accordingly.
216            
217             Perform the download regardless of the current status.
218            
219             $rsStart, $rsReceived, $rsCheckCancel are sub refs which are called
220             during the download.
221            
222             $rsStart->($contentLength)
223             Called once.
224            
225             $rsReceived->($bytesReceived)
226             Called for each chunk downloaded.
227            
228             $rsCheckCancel->()
229             Called for each chunk. Should return true if the download should be
230             cancelled, else false.
231            
232             Return 1, die on errors.
233            
234             =cut
235             sub download {
236 0     0 1   my $self = shift;
237 0           my ($rsStart, $rsReceived, $rsCheckCancel) = @_;
238 0   0 0     $rsStart ||= sub {};
  0            
239 0   0 0     $rsReceived ||= sub {};
  0            
240 0   0 0     $rsCheckCancel ||= sub {};
  0            
241 0           my $updateEvery = 1000;
242            
243 0           eval {
244 0           my $url = $self->url;
245            
246 0           my $oBrowser = LWP::UserAgent->new(
247             env_proxy => 0,
248             timeout => 50,
249             keep_alive => 1,
250             agent => "Internet Explorer 5.5 on Windows 2000: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)",
251             );
252 0           my $oRequest = HTTP::Request->new(GET => $url);
253 0 0         $self->urlReferer and $oRequest->referer($self->urlReferer);
254            
255 0           my $content = "";
256 0           my $once = 0;
257 0           my $bytesReceived = 0;
258             my $oResponse = $oBrowser->request(
259             $oRequest,
260             sub {
261 0     0     my ($chunk, $oResponse) = @_;
262            
263 0 0 0       $once++ or $rsStart->($oResponse->content_length || 1);
264            
265 0           $bytesReceived += length($chunk);
266 0   0       $rsReceived->($bytesReceived || 1);
267            
268 0           $content .= $chunk;
269            
270 0 0         $rsCheckCancel->() and die("Cancelled\n");
271            
272 0 0         $once % $updateEvery or $self->setBytesDownloaded($bytesReceived);
273             }
274 0           );
275            
276 0 0         $oResponse->is_success or die("Could not get url ($url) (" . $oResponse->status_line . ")\n");
277 0 0         defined($content) or warn("Could not get URL ($url) (no content)\n"), return(0);
278            
279            
280 0           my $nameDir = $self->dirDownload();
281 0           my $nameFile = "$nameDir/" . $self->fileDownload;
282            
283 0           mkpath($nameDir);
284 0 0         -d $nameDir or warn("No dir ($nameDir)\n"), return(0);
285            
286 0           write_file($nameFile, { binmode => ":raw", }, $content);
287            
288 0           undef $content;
289            
290             };
291            
292 0           $self->setDone;
293            
294 0 0         $@ and die;
295            
296 0           return(1);
297             }
298            
299            
300            
301            
302            
303             =head1 CLASS METHODS
304            
305             =head2 domainFromUrl($url)
306            
307             Return the domain part of $url, or "" if none was found.
308            
309             Die on errors.
310            
311             =cut
312             sub domainFromUrl {
313 0     0 1   my $pkg = shift;
314 0           my ($url) = @_;
315            
316 0 0         $url =~ m|^\w+ : // (?: [^\@]+ \@ )? ([\w\.]+) |msx or return("");
317 0           my $domain = $1;
318            
319 0           return($domain);
320             }
321            
322            
323            
324            
325            
326             =head2 bytesContentFromUrl($url, [$urlReferer = ""])
327            
328             Return the Content-Length of HEAD $url, or 0 if none was found.
329            
330             Die on errors.
331            
332             =cut
333             sub bytesContentFromUrl {
334 0     0 1   my $pkg = shift;
335 0           my ($url, $urlReferer) = @_;
336 0   0       $urlReferer ||= "";
337            
338 0           my $oBrowser = LWP::UserAgent->new(
339             env_proxy => 0,
340             timeout => 50,
341             keep_alive => 1,
342             agent => "Internet Explorer 5.5 on Windows 2000: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)",
343             );
344 0           my $oRequest = HTTP::Request->new(HEAD => $url);
345 0 0         $urlReferer and $oRequest->referer($urlReferer);
346 0           my $oResponse = $oBrowser->request($oRequest);
347 0 0         $oResponse->is_success or return(0);
348 0   0       return( $oResponse->header("Content-Length") || 0 );
349             }
350            
351            
352            
353            
354            
355             1;
356            
357            
358            
359            
360            
361             __END__