spikingjelly.activation_based.ann2snn.utils 源代码
import os
import re
import requests
from tqdm import tqdm
def _validate_download_response(req, first_byte, file_size):
if req.status_code not in (200, 206):
req.raise_for_status()
if req.status_code == 200:
if first_byte != 0:
return False
return True
content_range = req.headers.get("Content-Range", "")
match = re.match(r"bytes (\d+)-(\d+)/(\d+)", content_range, re.IGNORECASE)
return (
match is not None
and int(match.group(1)) == first_byte
and int(match.group(2)) == file_size - 1
and int(match.group(3)) == file_size
)
def _download_without_resume(url, dst, headers):
pbar = tqdm(unit="B", unit_scale=True, desc=dst)
req = None
written = 0
try:
req = requests.get(url, headers=headers, stream=True, timeout=30)
req.raise_for_status()
with open(dst, "wb") as f:
for chunk in req.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
written += len(chunk)
pbar.update(len(chunk))
finally:
if req is not None:
req.close()
pbar.close()
return written
[文档]
def download_url(url: str, dst: str) -> int:
r"""
**API Language** - :ref:`中文 <download_url-cn>` | :ref:`English <download_url-en>`
----
.. _download_url-cn:
* **中文**
从指定 URL 下载文件并保存到目标路径。支持断点续传。
:param url: 文件的下载链接
:type url: str
:param dst: 保存文件的目标路径
:type dst: str
:return: 文件的总大小(以字节为单位)。若服务器没有返回
``content-length``,则返回实际下载的字节数。
:rtype: int
:raises RuntimeError: 当服务器响应不符合断点续传要求,或实际接收字节数与声明长度不一致时抛出
----
.. _download_url-en:
* **English**
Download a file from a given URL and save it to a destination path. Supports resuming interrupted downloads.
:param url: the download URL of the file
:type url: str
:param dst: the destination path to save the file
:type dst: str
:return: the total file size in bytes. If the server does not return
``content-length``, this function returns the actually downloaded byte count.
:rtype: int
:raises RuntimeError: Raised when the server response is invalid for resume, or when the received byte count does not match the declared length
"""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0"
}
response = requests.get(url, headers=headers, stream=True, timeout=30) # (1)
try:
response.raise_for_status()
content_length = response.headers.get("content-length")
finally:
response.close()
if content_length is None:
return _download_without_resume(url, dst, headers)
file_size = int(content_length) # (2)
if os.path.exists(dst):
first_byte = os.path.getsize(dst) # (3)
else:
first_byte = 0
if first_byte >= file_size: # (4)
return file_size
header = {**headers, "Range": f"bytes={first_byte}-{file_size - 1}"}
pbar = tqdm(
total=file_size, initial=first_byte, unit="B", unit_scale=True, desc=dst
)
req = None
try:
req = requests.get(url, headers=header, stream=True, timeout=30) # (5)
mode = "ab"
valid_response = _validate_download_response(req, first_byte, file_size)
if first_byte > 0 and not valid_response:
req.close()
first_byte = 0
pbar.reset(total=file_size)
header = {**headers, "Range": f"bytes=0-{file_size - 1}"}
req = requests.get(url, headers=header, stream=True, timeout=30)
valid_response = _validate_download_response(req, first_byte, file_size)
mode = "wb"
if not valid_response:
raise RuntimeError("Invalid response for download.")
written = 0
with open(dst, mode) as f:
for chunk in req.iter_content(chunk_size=1024): # (6)
if chunk:
f.write(chunk)
written += len(chunk)
pbar.update(len(chunk))
expected_bytes = file_size - first_byte
if written != expected_bytes:
raise RuntimeError(
f"Downloaded {written} bytes, but expected {expected_bytes} bytes."
)
finally:
if req is not None:
req.close()
pbar.close()
return file_size