Async Download to Library with progress; Download to client
Backend: - DownloadTask model + background thread runner: streams the file with progress (%, bytes, speed) and a cancel flag, then indexes it, names it J-<id>.<ext> and applies the e621 metadata - DownloadTaskViewSet (create/retrieve/cancel) replaces the synchronous endpoint; the status footer's worker counts now reflect download jobs - Client download proxy (/api/online/file/) streams an e621 original to the browser with Content-Disposition: attachment, restricted to the configured e621 CDN hosts so it cannot be used as an open proxy Frontend: - Online detail: progress bar with percentage, transferred size, speed and cancel while downloading; success links to the new J-ID - New 'Download to client' button available to everyone (guests too)
This commit is contained in:
@@ -189,17 +189,32 @@ def serve_file(request, path, download=False):
|
||||
return response
|
||||
|
||||
|
||||
def download_file(url, destination):
|
||||
class DownloadCancelled(Exception):
|
||||
"""Raised when a streamed download is cancelled by the user."""
|
||||
|
||||
|
||||
def download_file(
|
||||
url, destination, progress_callback=None, should_cancel=None
|
||||
):
|
||||
"""Stream a remote file into destination (used by Download to Library)."""
|
||||
import requests
|
||||
|
||||
headers = {"User-Agent": settings.USER_AGENT}
|
||||
with requests.get(url, headers=headers, stream=True, timeout=120) as response:
|
||||
response.raise_for_status()
|
||||
total = int(response.headers.get("content-length") or 0)
|
||||
downloaded = 0
|
||||
with open(destination, "wb") as handle:
|
||||
for chunk in response.iter_content(chunk_size=CHUNK_SIZE):
|
||||
if should_cancel is not None and should_cancel():
|
||||
raise DownloadCancelled("download cancelled")
|
||||
if chunk:
|
||||
handle.write(chunk)
|
||||
downloaded += len(chunk)
|
||||
if progress_callback is not None:
|
||||
progress_callback(downloaded, total)
|
||||
if progress_callback is not None:
|
||||
progress_callback(downloaded, total or downloaded)
|
||||
|
||||
|
||||
E621_DESCRIPTION_LIMIT = 20000
|
||||
|
||||
Reference in New Issue
Block a user