downloader.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. from inspect import iscoroutinefunction
  2. from os.path import abspath as absolute_path
  3. from time import time
  4. import aiofiles
  5. from wbb import aiohttpsession as session
  6. from wbb.core.tasks import add_task, rm_task
  7. def ensure_status(status_code: int):
  8. if status_code < 200 or status_code >= 300:
  9. raise Exception(f"HttpProcessingError: {status_code}")
  10. async def download_url(
  11. url,
  12. file_path,
  13. chunk_size,
  14. ):
  15. file_path = file_path or url.split("/")[-1][:20]
  16. async with session.get(url) as response:
  17. ensure_status(response.status)
  18. async with aiofiles.open(file_path, "wb") as f:
  19. # Save content in file using aiohttp streamReader.
  20. async for chunk in response.content.iter_chunked(
  21. chunk_size
  22. ):
  23. await f.write(chunk)
  24. return absolute_path(file_path)
  25. async def download(
  26. url: str,
  27. file_path: str = None,
  28. chunk_size: int = 1000000, # 1MB chunk
  29. task_id: int = int(time()),
  30. ):
  31. """
  32. :url: url where the file is located
  33. :file_path: path/to/file
  34. :chunk_size: size of a single chunk
  35. Returns:
  36. (asyncio.Task, task_id), With which you can await
  37. the task, track task progress or cancel it.
  38. """
  39. # Create a task and add it to main tasks dict
  40. # So we can cancel it using .cancelTask
  41. task, task_id = await add_task(
  42. download_url,
  43. "Downloader",
  44. url=url,
  45. file_path=file_path,
  46. chunk_size=chunk_size,
  47. )
  48. return task, task_id