Here is an example of how to build a download manager.
We start by defining a function that uses URLDownloadSubmit
to initiate a download:
manifest = <||>;
SetAttributes[taskProgress, HoldFirst]
taskProgress[manifest_][event_] :=
manifest = <|manifest, event["Task"] -> event|>
SetAttributes[taskFinished, HoldFirst]
taskFinished[manifest_][event_] :=
manifest = <|manifest, event["Task"] -> event|>
SetAttributes[startJob, HoldFirst]
startJob[manifest_][src_, dest_] := URLDownloadSubmit[
src, dest,
HandlerFunctions -> <|
"ConnectionFailed" -> connectionFailed[manifest],
"CookiesReceived" -> cookiesReceived[manifest],
"HeadersReceived" -> headersReceived[manifest],
"TaskFinished" -> taskFinished[manifest],
"TaskProgress" -> taskProgress[manifest],
"TaskStatusChanged" -> taskStatusChanged[manifest]
|>,
HandlerFunctionsKeys -> {
"Task", "TaskStatus", "File",
"ByteCountTotal", "ByteCountDownloaded", "FractionComplete"
}
];
We have defined a variable, manifest
, that will hold information about the files being downloaded. It is up to the user to define the event handler functions that they want to use; in my download manager, I will only use TaskProgress
and TaskFinished
. Whenever any of those events are called, I update manifest
with the latest information. The latest information includes the variables specified under HandleFunctionsKeys
.
This is all we need, really. Now we can build an interface to visualize manifest
.
SetAttributes[abortDownload, HoldFirst]
abortDownload[manifest_, task_] := (
TaskRemove /@ Select[Tasks[], #["TaskUUID"] === task["TaskUUID"] &];
manifest = <|
manifest,
task -> <|manifest[task], "TaskStatus" -> "Aborted"|>
|>)
SetAttributes[visualizeManifest, HoldFirst]
visualizeManifest[manifest_] := TableForm[Join[
{{"File", "Size (MB)", "Downloaded (MB)", "Fraction complete",
"Status", ""}}, {
#File
, Floor[#ByteCountTotal/10^6]
, Floor[#ByteCountDownloaded/10^6]
, ProgressIndicator[#FractionComplete]
, #TaskStatus
, Button["Abort", abortDownload[manifest, #Task],
Enabled -> (#TaskStatus =!= "Aborted")]
} & /@ Values[manifest]
]]
I will also add a button to begin downloading an Anaconda installer. Anaconda is a software for Python programmers that I picked because the installer is large enough in size that the download won't finish in a blip.
i = 0;
Button["Download", startJob[manifest][
"https://repo.anaconda.com/archive/Anaconda3-5.2.0-MacOSX-x86_64.pkg",
"~/Downloads/anaconda" <> ToString[i++] <> ".pkg"
]]
Dynamic@visualizeManifest[manifest]
The final result looks like this:

You can easily compute other statistics such as how many of the files have finished downloading by going through the values in the manifest
association.