Line data Source code
1 : #include "BatchDownloadCore.h"
2 : #include "FangNetworkAccessManager.h"
3 :
4 : #include <QSet>
5 :
6 59 : BatchDownloadCore::BatchDownloadCore(int timeoutMs,
7 : int maxRedirects,
8 : QObject* parent,
9 59 : QNetworkAccessManager* networkManager)
10 : : FangObject(parent)
11 59 : , manager(networkManager ? networkManager : new FangNetworkAccessManager(this))
12 118 : , totalCount(0)
13 : {
14 59 : config.timeoutMs = timeoutMs;
15 59 : config.maxRedirects = maxRedirects;
16 59 : }
17 :
18 118 : BatchDownloadCore::~BatchDownloadCore()
19 : {
20 59 : abort();
21 118 : }
22 :
23 35 : void BatchDownloadCore::download(const QList<QUrl>& urls)
24 : {
25 : // Clear previous.
26 35 : abort();
27 35 : _results.clear();
28 :
29 : // Handle empty list.
30 35 : if (urls.isEmpty()) {
31 1 : totalCount = 0;
32 1 : emit finished();
33 1 : return;
34 : }
35 :
36 : // Deduplicate URL list.
37 34 : QList<QUrl> uniqueUrls;
38 34 : QSet<QUrl> seen;
39 104 : for (const QUrl& url : urls) {
40 70 : if (!seen.contains(url)) {
41 68 : seen.insert(url);
42 68 : uniqueUrls.append(url);
43 : }
44 : }
45 :
46 34 : totalCount = uniqueUrls.size();
47 :
48 : // Create a NetworkDownloadCore for each URL.
49 102 : for (const QUrl& url : uniqueUrls) {
50 68 : auto* downloader = new NetworkDownloadCore(config, nullptr, manager);
51 :
52 68 : connect(downloader, &NetworkDownloadCore::finished,
53 68 : this, &BatchDownloadCore::onDownloadFinished);
54 68 : connect(downloader, &NetworkDownloadCore::error,
55 68 : this, &BatchDownloadCore::onDownloadError);
56 :
57 68 : downloaders[downloader] = url;
58 68 : downloader->download(url);
59 : }
60 34 : }
61 :
62 94 : void BatchDownloadCore::abort()
63 : {
64 : // STOP! and delete all downloaders.
65 94 : for (auto it = downloaders.begin(); it != downloaders.end(); ++it) {
66 0 : NetworkDownloadCore* downloader = it.key();
67 0 : downloader->abort();
68 0 : delete downloader;
69 : }
70 :
71 94 : downloaders.clear();
72 94 : }
73 :
74 60 : void BatchDownloadCore::onDownloadFinished(const QUrl& finalUrl, const QByteArray& data)
75 : {
76 60 : auto* downloader = qobject_cast<NetworkDownloadCore*>(sender());
77 60 : if (!downloader || !downloaders.contains(downloader)) {
78 0 : return;
79 : }
80 :
81 60 : QUrl originalUrl = downloaders.take(downloader);
82 60 : downloader->deleteLater();
83 :
84 60 : BatchDownloadResult result;
85 60 : result.success = true;
86 60 : result.data = data;
87 60 : result.finalUrl = finalUrl;
88 :
89 60 : _results[originalUrl] = result;
90 :
91 60 : emit progress(_results.size(), totalCount);
92 60 : checkCompletion();
93 60 : }
94 :
95 8 : void BatchDownloadCore::onDownloadError(const QUrl& url, const QString& errorString)
96 : {
97 : Q_UNUSED(url);
98 :
99 8 : auto* downloader = qobject_cast<NetworkDownloadCore*>(sender());
100 8 : if (!downloader || !downloaders.contains(downloader)) {
101 0 : return;
102 : }
103 :
104 8 : QUrl originalUrl = downloaders.take(downloader);
105 8 : downloader->deleteLater();
106 :
107 8 : BatchDownloadResult result;
108 8 : result.success = false;
109 8 : result.errorString = errorString;
110 :
111 8 : _results[originalUrl] = result;
112 :
113 8 : emit progress(_results.size(), totalCount);
114 8 : checkCompletion();
115 8 : }
116 :
117 68 : void BatchDownloadCore::checkCompletion()
118 : {
119 68 : if (_results.size() == totalCount) {
120 34 : emit finished();
121 : }
122 68 : }
|