feat: implement hydra-httpdl for download management

This commit is contained in:
Hachi-R
2025-04-10 15:43:38 -03:00
parent 98ed07d6d2
commit 84600ea0dc

View File

@@ -1,61 +1,89 @@
import aria2p
import os
import subprocess
import json
class HttpDownloader:
def __init__(self):
self.download = None
self.aria2 = aria2p.API(
aria2p.Client(
host="http://localhost",
port=6800,
secret=""
)
)
def __init__(self):
self.binaries_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "binaries")
self.hydra_exe = os.path.join(self.binaries_path, "hydra-httpdl.exe")
self.process = None
self.last_status = None
def start_download(self, url: str, save_path: str, header: str, out: str = None, allow_multiple_connections: bool = False):
if self.download:
self.aria2.resume([self.download])
else:
options = {
"header": header,
"dir": save_path,
"out": out
}
def start_download(self, url: str, save_path: str, header: str = None, out: str = None, allow_multiple_connections: bool = False):
cmd = [self.hydra_exe]
cmd.append(url)
cmd.extend([
"--chunk-size", "10",
"--buffer-size", "16",
"--json-output",
"--silent"
])
if allow_multiple_connections:
cmd.extend(["--connections", "24"])
print(f"running hydra-httpdl: {' '.join(cmd)}")
try:
self.process = subprocess.Popen(
cmd,
cwd=save_path,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
)
except Exception as e:
print(f"error running hydra-httpdl: {e}")
if allow_multiple_connections:
options.update({
"split": "16",
"max-connection-per-server": "16",
"min-split-size": "1M"
})
downloads = self.aria2.add(url, options=options)
def get_download_status(self):
if not self.process:
return None
try:
line = self.process.stdout.readline()
if line:
status = json.loads(line.strip())
self.last_status = status
elif self.last_status:
status = self.last_status
else:
return None
response = {
"status": "active",
"progress": status["progress"] / 100,
"downloadSpeed": status["download_speed"],
"numPeers": 0,
"numSeeds": 0,
"bytesDownloaded": status["bytes_downloaded"],
"fileSize": status["file_size"],
"folderName": status["file_name"]
}
if status["progress"] == 100.0:
response["status"] = "complete"
return response
except Exception as e:
print(f"error getting download status: {e}")
return None
self.download = downloads[0]
def pause_download(self):
if self.download:
self.aria2.pause([self.download])
def cancel_download(self):
if self.download:
self.aria2.remove([self.download])
self.download = None
def get_download_status(self):
if self.download == None:
return None
download = self.aria2.get_download(self.download.gid)
response = {
'folderName': download.name,
'fileSize': download.total_length,
'progress': download.completed_length / download.total_length if download.total_length else 0,
'downloadSpeed': download.download_speed,
'numPeers': 0,
'numSeeds': 0,
'status': download.status,
'bytesDownloaded': download.completed_length,
}
return response
def stop_download(self):
if self.process:
self.process.terminate()
self.process = None
self.last_status = None
def pause_download(self):
self.stop_download()
def cancel_download(self):
self.stop_download()