UI: Use QtNetwork for downloads.

Installer: Remove `curl.*` later.
This commit is contained in:
Nodir Temirkhodjaev 2021-08-28 17:46:24 +03:00
parent 6afc993876
commit d75e02d3fb
4 changed files with 80 additions and 72 deletions

View File

@ -91,6 +91,7 @@ Filename: "{app}\driver\scripts\uninstall.bat"; RunOnceId: "DelDriver"
Type: filesandordirs; Name: "{app}\driver"
Type: filesandordirs; Name: "{app}\i18n"
Type: filesandordirs; Name: "{app}\plugins"
; TODO: COMPAT: Remove the following line after v4.1.0
Type: files; Name: "{app}\curl*.*"
Type: files; Name: "{app}\qt*.*"
Type: files; Name: "{app}\README*.*"

View File

@ -47,8 +47,7 @@ cd %TARGET_PATH%
-no-feature-mimetype-database -no-feature-sql -no-feature-sql-odbc ^
^
-no-feature-getifaddrs -no-feature-ipv6ifname -no-feature-libproxy ^
-no-feature-openssl -no-feature-schannel -no-feature-ssl -no-feature-sctp ^
-no-feature-system-proxies -no-feature-http -no-feature-udpsocket ^
-no-feature-openssl -schannel -ssl -no-feature-sctp -no-feature-udpsocket ^
-no-feature-networkproxy -no-feature-socks5 -no-feature-networkdiskcache ^
-no-feature-dnslookup -no-feature-sspi -no-feature-networklistmanager ^
^

View File

@ -1,51 +1,80 @@
#include "netdownloader.h"
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#define DOWNLOAD_TIMEOUT 30 // 30 seconds timeout
#define DOWNLOAD_MAXSIZE (64 * 1024)
#define DOWNLOAD_TIMEOUT (30 * 1000) // 30 milliseconds timeout
#define DOWNLOAD_MAXSIZE (8 * 1024 * 1024)
NetDownloader::NetDownloader(QObject *parent) : QObject(parent), m_started(false), m_aborted(false)
NetDownloader::NetDownloader(QObject *parent) :
QObject(parent), m_started(false), m_aborted(false), m_manager(new QNetworkAccessManager(this))
{
setupProcess();
}
m_downloadTimer.setInterval(DOWNLOAD_TIMEOUT);
void NetDownloader::setupProcess()
{
connect(&m_process, &QProcess::readyReadStandardOutput, this, &NetDownloader::processReadyRead);
connect(&m_process, &QProcess::errorOccurred, this, &NetDownloader::processError);
connect(&m_process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this,
&NetDownloader::processFinished);
connect(&m_downloadTimer, &QTimer::timeout, this, [&] {
qDebug() << "NetDownloader: Error: Download timed out";
finish();
});
}
void NetDownloader::start()
{
QStringList args;
args.append("--max-time");
args.append(QString::number(DOWNLOAD_TIMEOUT));
if (!m_data.isEmpty()) {
args.append("--data");
args.append(QString::fromLatin1(m_data.constData()));
}
args.append(m_url);
qDebug() << "NetDownloader: Start:" << url() << data();
m_started = true;
m_aborted = false;
m_buffer.clear();
m_process.start("curl", args, QIODevice::ReadOnly);
m_downloadTimer.start();
qDebug() << "NetDownloader: Run `curl`:" << args;
QNetworkRequest request(url());
if (!m_process.waitForStarted(1000)) {
qWarning() << "NetDownloader: Cannot start `curl`:" << m_process.errorString();
if (!m_data.isEmpty()) {
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
m_reply = m_manager->post(request, data());
} else {
m_reply = m_manager->get(request);
}
connect(m_reply, &QNetworkReply::downloadProgress, this,
[&](qint64 bytesReceived, qint64 /*bytesTotal*/) {
if (m_aborted || bytesReceived == 0)
return;
const QByteArray data = m_reply->read(DOWNLOAD_MAXSIZE - m_buffer.size());
m_buffer.append(data);
if (m_buffer.size() >= DOWNLOAD_MAXSIZE) {
qWarning() << "NetDownloader: Error: Too big file";
finish();
}
});
connect(m_reply, &QNetworkReply::finished, this, [&] {
const bool success = (m_reply->error() == QNetworkReply::NoError);
finish(success && !m_buffer.isEmpty());
});
connect(m_reply, &QNetworkReply::errorOccurred, this, [&](QNetworkReply::NetworkError error) {
if (m_aborted)
return;
qWarning() << "NetDownloader: Error:" << error << m_reply->errorString();
finish();
}
});
connect(m_reply, &QNetworkReply::sslErrors, this, [&](const QList<QSslError> &errors) {
if (m_aborted)
return;
for (const QSslError &error : errors) {
qWarning() << "NetDownloader: SSL Error:" << error.errorString();
}
finish();
});
}
void NetDownloader::finish(bool success)
@ -56,38 +85,15 @@ void NetDownloader::finish(bool success)
m_started = false;
m_aborted = true;
m_process.kill();
m_process.waitForFinished();
m_downloadTimer.stop();
if (m_reply) {
m_reply->abort();
m_reply->close();
m_reply->deleteLater();
m_reply = nullptr;
}
emit finished(success);
}
void NetDownloader::processReadyRead()
{
const QByteArray data = m_process.read(DOWNLOAD_MAXSIZE - m_buffer.size());
m_buffer.append(data);
if (m_buffer.size() > DOWNLOAD_MAXSIZE) {
finish(true); // try to use the partial loaded data
}
}
void NetDownloader::processError(QProcess::ProcessError error)
{
if (m_aborted)
return;
qWarning() << "NetDownloader: Cannot run `curl`:" << error << m_process.errorString();
finish();
}
void NetDownloader::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
const bool success = (exitCode == 0 && exitStatus == QProcess::NormalExit);
if (!success) {
qWarning() << "NetDownloader: `curl` error code:" << exitCode;
}
finish(success && !m_buffer.isEmpty());
}

View File

@ -1,7 +1,11 @@
#ifndef NETDOWNLOADER_H
#define NETDOWNLOADER_H
#include <QProcess>
#include <QObject>
#include <QTimer>
QT_FORWARD_DECLARE_CLASS(QNetworkAccessManager)
QT_FORWARD_DECLARE_CLASS(QNetworkReply)
class NetDownloader : public QObject
{
@ -10,7 +14,10 @@ class NetDownloader : public QObject
public:
explicit NetDownloader(QObject *parent = nullptr);
QString url() const { return m_url; }
void setUrl(const QString &url) { m_url = url; }
QByteArray data() const { return m_data; }
void setData(const QByteArray &data) { m_data = data; }
QByteArray buffer() const { return m_buffer; }
@ -23,14 +30,6 @@ public slots:
void start();
void finish(bool success = false);
private slots:
void processReadyRead();
void processError(QProcess::ProcessError error);
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
private:
void setupProcess();
private:
bool m_started : 1;
bool m_aborted : 1;
@ -38,9 +37,12 @@ private:
QString m_url;
QByteArray m_data;
QProcess m_process;
QByteArray m_buffer;
QTimer m_downloadTimer;
QNetworkAccessManager *m_manager = nullptr;
QNetworkReply *m_reply = nullptr;
};
#endif // NETDOWNLOADER_H