Files
mcp_screen/lib/download_util.py

69 lines
2.1 KiB
Python

import os
import urequests
from sd_util import SDCardManager
def download_file(url, dest_filename, use_sd=True):
"""Downloads a file from a URL over the network in memory-efficient chunks.
If use_sd is True, it automatically mounts the microSD card and saves to /sd/dest_filename.
Otherwise, it saves to the local flash storage.
Returns:
str: The full path to the downloaded file on success, None on failure.
"""
dest_path = dest_filename
sd_manager = None
if use_sd:
sd_manager = SDCardManager(mount_point='/sd')
if not sd_manager.mount():
print("Download Error: Could not mount SD card.")
return None
dest_path = f"/sd/{dest_filename}"
print(f"Starting download from: {url} -> {dest_path}")
try:
res = urequests.get(url, stream=True)
except Exception as e:
print(f"HTTP Connection failed: {e}")
return None
if res.status_code != 200:
print(f"HTTP Error: Received status code {res.status_code}")
res.close()
return None
try:
# Read from socket stream in chunks to avoid OutOfMemory errors
chunk_size = 4096
total_downloaded = 0
with open(dest_path, 'wb') as f:
while True:
# Read chunk from the raw socket connection stream
chunk = res.raw.read(chunk_size)
if not chunk:
break
f.write(chunk)
total_downloaded += len(chunk)
# Dynamic logging
if total_downloaded % (chunk_size * 25) == 0:
print(f"Downloaded {total_downloaded // 1024} KB...")
print(f"Download complete! Saved {total_downloaded} bytes to '{dest_path}'.")
return dest_path
except Exception as e:
print(f"Error writing to file: {e}")
# Clean up partial file on failure
try:
os.remove(dest_path)
except:
pass
return None
finally:
res.close()