2019-01-29 13:46:24 +00:00
|
|
|
import os
|
2022-08-15 05:12:10 +00:00
|
|
|
import httpx
|
2019-01-29 13:46:24 +00:00
|
|
|
|
|
|
|
CHUNK_SIZE = 1024
|
|
|
|
CONNECT_TIMEOUT = 5
|
2020-04-10 14:22:15 +00:00
|
|
|
RETRY_COUNT = 5
|
2019-01-29 13:46:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
class DownloadFailed(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2022-08-20 09:35:07 +00:00
|
|
|
def _download(url: str, path: str):
|
2019-01-29 13:46:24 +00:00
|
|
|
tmp_path = path + ".tmp"
|
|
|
|
size = 0
|
2022-08-15 05:12:10 +00:00
|
|
|
with httpx.stream("GET", url, timeout=CONNECT_TIMEOUT) as response:
|
|
|
|
with open(tmp_path, "wb") as target:
|
|
|
|
for chunk in response.iter_bytes(chunk_size=CHUNK_SIZE):
|
|
|
|
target.write(chunk)
|
|
|
|
size += len(chunk)
|
2019-01-29 13:46:24 +00:00
|
|
|
|
|
|
|
os.rename(tmp_path, path)
|
|
|
|
return size
|
|
|
|
|
|
|
|
|
2022-08-20 09:35:07 +00:00
|
|
|
def download_file(url: str, path: str, retries: int = RETRY_COUNT):
|
2019-01-29 13:46:24 +00:00
|
|
|
if os.path.exists(path):
|
2021-09-16 01:53:02 +00:00
|
|
|
from_disk = True
|
|
|
|
return (os.path.getsize(path), from_disk)
|
2019-01-29 13:46:24 +00:00
|
|
|
|
2021-09-16 01:53:02 +00:00
|
|
|
from_disk = False
|
2019-01-29 13:46:24 +00:00
|
|
|
for _ in range(retries):
|
|
|
|
try:
|
2021-09-16 01:53:02 +00:00
|
|
|
return (_download(url, path), from_disk)
|
2022-08-15 05:12:10 +00:00
|
|
|
except httpx.RequestError:
|
2020-04-10 14:22:15 +00:00
|
|
|
pass
|
2019-01-29 13:46:24 +00:00
|
|
|
|
|
|
|
raise DownloadFailed(":(")
|