Source code for pyanimeinfo.utils.download

import os

import pyrfc6266
import requests

from .session import get_session
from .tqdm_ import tqdm


[docs]def download_file(url, filename=None, output_directory=None, expected_size: int = None, desc=None, session=None, silent: bool = False, **kwargs): """ Download a file from a given URL to the local file system. This function downloads a file from a specified URL and saves it to the local file system. It supports optional parameters such as specifying the output filename, output directory, and expected file size. :param url: The URL from which to download the file. :type url: str :param filename: The local filename to save the downloaded file. If not provided, the function tries to extract it from the response headers. :type filename: str, optional :param output_directory: The directory where the downloaded file should be saved. If provided, the filename is combined with this directory. :type output_directory: str, optional :param expected_size: The expected size of the downloaded file in bytes. If specified, the function checks whether the downloaded file size matches the expected size. :type expected_size: int, optional :param desc: The description to be displayed during the download progress (e.g., in a progress bar). :type desc: str, optional :param session: An optional `requests.Session` object to be used for making the HTTP request. :type session: requests.Session, optional :param silent: If True, suppresses the progress bar and download progress display. :type silent: bool :param **kwargs: Additional keyword arguments to pass to the `requests.get` method. :return: The filename where the downloaded file is saved. :rtype: str :raises requests.exceptions.HTTPError: If the downloaded file size does not match the expected size (if provided). """ session = session or get_session() response = session.get(url, stream=True, allow_redirects=True, **kwargs) expected_size = expected_size or response.headers.get('Content-Length', None) if filename is None: filename = pyrfc6266.parse_filename(response.headers.get('Content-Disposition')) if output_directory is not None: filename = os.path.join(output_directory, filename) expected_size = int(expected_size) if expected_size is not None else expected_size desc = desc or os.path.basename(filename) directory = os.path.dirname(filename) if directory: os.makedirs(directory, exist_ok=True) with open(filename, 'wb') as f: with tqdm(total=expected_size, unit='B', unit_scale=True, unit_divisor=1024, desc=desc, silent=silent) as pbar: for chunk in response.iter_content(chunk_size=1024): f.write(chunk) pbar.update(len(chunk)) actual_size = os.path.getsize(filename) if expected_size is not None and actual_size != expected_size: os.remove(filename) raise requests.exceptions.HTTPError(f"Downloaded file is not of expected size, " f"{expected_size} expected but {actual_size} found.") return filename