|
1 | 1 | import re |
| 2 | +import requests |
2 | 3 | from datetime import datetime |
3 | 4 | import hashlib |
4 | 5 | import time |
@@ -298,8 +299,61 @@ def _append_file_to_download(self, rfile): |
298 | 299 | rfile['url'] = self.url |
299 | 300 | if 'root' not in rfile or not rfile['root']: |
300 | 301 | rfile['root'] = self.rootdir |
| 302 | + |
| 303 | + if rfile.get('modified_size'): |
| 304 | + # Size parsed is inacurate. Try to get a more accurate size with a HEAD query |
| 305 | + try: |
| 306 | + self.logger.debug('Trying to get a more accurate size for ' + rfile['name']) |
| 307 | + head_size = self._estimate_size(rfile) |
| 308 | + if head_size: |
| 309 | + rfile['size'] = head_size |
| 310 | + except Exception as e: |
| 311 | + self.logger.error('Exception while trying to get a more accurate size for ' + rfile['name'] + ' - ' + str(e)) |
| 312 | + |
301 | 313 | super(CurlDownload, self)._append_file_to_download(rfile) |
302 | 314 |
|
| 315 | + def _estimate_size(self, rfile): |
| 316 | + # Cannot reuse _file_url, since we did not cleanup the name yet |
| 317 | + # Mostly pasted for the same stuff in direct download |
| 318 | + name = re.sub('//+', '/', rfile['name']) |
| 319 | + url = self.url + '/' + rfile['root'] + name |
| 320 | + url_elts = url.split('://') |
| 321 | + if len(url_elts) == 2: |
| 322 | + url_elts[1] = re.sub("/{2,}", "/", url_elts[1]) |
| 323 | + full_url = '://'.join(url_elts) |
| 324 | + else: |
| 325 | + full_url = re.sub("/{2,}", "/", url) |
| 326 | + |
| 327 | + return self._head_size_call(full_url) |
| 328 | + |
| 329 | + def _head_size_call(self, full_url): |
| 330 | + # Now do a HEAD call on this url |
| 331 | + |
| 332 | + auth = () |
| 333 | + proxies = {} |
| 334 | + |
| 335 | + if self.credentials is not None: |
| 336 | + auth = tuple(self.credentials.split(":")) |
| 337 | + |
| 338 | + if self.proxy is not None: |
| 339 | + proxy = self.proxy |
| 340 | + if not self.proxy.startswith("http"): |
| 341 | + proxy = 'http://' + self.proxy |
| 342 | + if self.proxy_auth is not None: |
| 343 | + # Don't really want to manage properly the various schemes |
| 344 | + proxy.replace('http://', 'http://{}@'.format(self.proxy_auth)) |
| 345 | + proxy.replace('https://', 'https://{}@'.format(self.proxy_auth)) |
| 346 | + proxies['http'] = proxy |
| 347 | + proxies['https'] = proxy |
| 348 | + |
| 349 | + try: |
| 350 | + size_response = requests.head(full_url, allow_redirects=True, auth=auth, proxies=proxies) |
| 351 | + size = int(size_response.headers.get('content-length', 0)) |
| 352 | + return size |
| 353 | + |
| 354 | + except Exception: |
| 355 | + return 0 |
| 356 | + |
303 | 357 | def _file_url(self, rfile): |
304 | 358 | # rfile['root'] is set to self.rootdir if needed but may be different. |
305 | 359 | # We don't use os.path.join because rfile['name'] may starts with / |
@@ -519,7 +573,12 @@ def _http_parse_result(self, result): |
519 | 573 | rfile['group'] = '' |
520 | 574 | rfile['user'] = '' |
521 | 575 | if self.http_parse.file_size != -1: |
522 | | - rfile['size'] = humanfriendly.parse_size(foundfile[self.http_parse.file_size - 1]) |
| 576 | + size = humanfriendly.parse_size(foundfile[self.http_parse.file_size - 1]) |
| 577 | + if not str(size) == foundfile[self.http_parse.file_size - 1]: |
| 578 | + # This is an approximation of the real size (conversion to byte) |
| 579 | + # We will check later (in match()) if we can get a more accurate size |
| 580 | + rfile['modified_size'] = True |
| 581 | + rfile['size'] = size |
523 | 582 | else: |
524 | 583 | rfile['size'] = 0 |
525 | 584 | if self.http_parse.file_date != -1: |
|
0 commit comments