| Index: platform_tools/android/bin/http_download.py
|
| diff --git a/platform_tools/android/bin/http_download.py b/platform_tools/android/bin/http_download.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..15f7983b7722afe2a43a781a2eb5b77d81826610
|
| --- /dev/null
|
| +++ b/platform_tools/android/bin/http_download.py
|
| @@ -0,0 +1,92 @@
|
| +#!/usr/bin/python
|
| +# Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Download a file from a URL to a file on disk.
|
| +
|
| +This module supports username and password with basic authentication.
|
| +"""
|
| +
|
| +import base64
|
| +import os
|
| +import os.path
|
| +import sys
|
| +import urllib2
|
| +
|
| +import download_utils
|
| +
|
| +
|
| +def _CreateDirectory(path):
|
| + """Create a directory tree, ignore if it's already there."""
|
| + try:
|
| + os.makedirs(path)
|
| + return True
|
| + except os.error:
|
| + return False
|
| +
|
| +
|
| +def HttpDownload(url, target, username=None, password=None, verbose=True,
|
| + logger=None):
|
| + """Download a file from a remote server.
|
| +
|
| + Args:
|
| + url: A URL to download from.
|
| + target: Filename to write download to.
|
| + username: Optional username for download.
|
| + password: Optional password for download (ignored if no username).
|
| + logger: Function to log events to.
|
| + """
|
| +
|
| + # Log to stdout by default.
|
| + if logger is None:
|
| + logger = sys.stdout.write
|
| + headers = [('Accept', '*/*')]
|
| + if username:
|
| + if password:
|
| + auth_code = base64.b64encode(username + ':' + password)
|
| + else:
|
| + auth_code = base64.b64encode(username)
|
| + headers.append(('Authorization', 'Basic ' + auth_code))
|
| + if os.environ.get('http_proxy'):
|
| + proxy = os.environ.get('http_proxy')
|
| + proxy_handler = urllib2.ProxyHandler({
|
| + 'http': proxy,
|
| + 'https': proxy})
|
| + opener = urllib2.build_opener(proxy_handler)
|
| + else:
|
| + opener = urllib2.build_opener()
|
| + opener.addheaders = headers
|
| + urllib2.install_opener(opener)
|
| + _CreateDirectory(os.path.split(target)[0])
|
| + # Retry up to 10 times (appengine logger is flaky).
|
| + for i in xrange(10):
|
| + if i:
|
| + logger('Download failed on %s, retrying... (%d)\n' % (url, i))
|
| + try:
|
| + # 30 second timeout to ensure we fail and retry on stalled connections.
|
| + src = urllib2.urlopen(url, timeout=30)
|
| + try:
|
| + download_utils.WriteDataFromStream(target, src, chunk_size=2**20,
|
| + verbose=verbose)
|
| + content_len = src.headers.get('Content-Length')
|
| + if content_len:
|
| + content_len = int(content_len)
|
| + file_size = os.path.getsize(target)
|
| + if content_len != file_size:
|
| + logger('Filesize:%d does not match Content-Length:%d' % (
|
| + file_size, content_len))
|
| + continue
|
| + finally:
|
| + src.close()
|
| + break
|
| + except urllib2.HTTPError, e:
|
| + if e.code == 404:
|
| + logger('Resource does not exist.\n')
|
| + raise
|
| + logger('Failed to open.\n')
|
| + except urllib2.URLError:
|
| + logger('Failed mid stream.\n')
|
| + else:
|
| + logger('Download failed on %s, giving up.\n' % url)
|
| + raise
|
|
|