QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgsfiledownloader.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfiledownloader.cpp
3 --------------------------------------
4 Date : November 2016
5 Copyright : (C) 2016 by Alessandro Pasotti
6 Email : apasotti at boundlessgeo dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsfiledownloader.h"
17
18#include "qgsapplication.h"
19#include "qgsauthmanager.h"
20#include "qgslogger.h"
23#include "qgsvariantutils.h"
24
25#include <QNetworkAccessManager>
26#include <QNetworkReply>
27#include <QNetworkRequest>
28#include <QString>
29
30#include "moc_qgsfiledownloader.cpp"
31
32using namespace Qt::StringLiterals;
33
34#ifndef QT_NO_SSL
35#include <QSslError>
36#endif
37
38QgsFileDownloader::QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg, bool delayStart, Qgis::HttpMethod httpMethod, const QByteArray &data )
39 : mUrl( url )
40 , mHttpMethod( httpMethod )
41 , mData( data )
42{
43 if ( !outputFileName.isEmpty() )
44 mFile.setFileName( outputFileName );
45 mAuthCfg = authcfg;
46 if ( !delayStart )
48}
49
50
52{
53 if ( mReply )
54 {
55 mReply->abort();
56 mReply->deleteLater();
57 }
58}
59
61{
63
64 QNetworkRequest request( mUrl );
65 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy );
66 QgsSetRequestInitiatorClass( request, u"QgsFileDownloader"_s );
67 if ( !mAuthCfg.isEmpty() )
68 {
70 }
71
72 if ( mReply )
73 {
74 disconnect( mReply, &QNetworkReply::readyRead, this, &QgsFileDownloader::onReadyRead );
75 disconnect( mReply, &QNetworkReply::finished, this, &QgsFileDownloader::onFinished );
76 disconnect( mReply, &QNetworkReply::downloadProgress, this, &QgsFileDownloader::onDownloadProgress );
77 mReply->abort();
78 mReply->deleteLater();
79 }
80
81 switch ( mHttpMethod )
82 {
84 {
85 mReply = nam->get( request );
86 break;
87 }
89 {
90 mReply = nam->post( request, mData );
91 break;
92 }
93
97 QgsDebugError( u"Unsupported HTTP method: %1"_s.arg( qgsEnumValueToKey( mHttpMethod ) ) );
98 // not supported
99 break;
100 }
101
102 if ( !mAuthCfg.isEmpty() )
103 {
104 QgsApplication::authManager()->updateNetworkReply( mReply, mAuthCfg );
105 }
106
107 connect( mReply, &QNetworkReply::readyRead, this, &QgsFileDownloader::onReadyRead );
108 connect( mReply, &QNetworkReply::finished, this, &QgsFileDownloader::onFinished );
109 connect( mReply, &QNetworkReply::downloadProgress, this, &QgsFileDownloader::onDownloadProgress );
110 connect( nam, qOverload< QNetworkReply *>( &QgsNetworkAccessManager::requestTimedOut ), this, &QgsFileDownloader::onRequestTimedOut, Qt::UniqueConnection );
111#ifndef QT_NO_SSL
112 connect( nam, &QgsNetworkAccessManager::sslErrors, this, &QgsFileDownloader::onSslErrors, Qt::UniqueConnection );
113#endif
114}
115
117{
118 mDownloadCanceled = true;
119 emit downloadCanceled();
120 onFinished();
121}
122
123void QgsFileDownloader::onRequestTimedOut( QNetworkReply *reply )
124{
125 if ( reply == mReply )
126 error( tr( "Network request %1 timed out" ).arg( mUrl.toString() ) );
127}
128
129#ifndef QT_NO_SSL
130void QgsFileDownloader::onSslErrors( QNetworkReply *reply, const QList<QSslError> &errors )
131{
132 if ( reply == mReply )
133 {
134 QStringList errorMessages;
135 errorMessages.reserve( errors.size() + 1 );
136 errorMessages << u"SSL Errors: "_s;
137
138 for ( const QSslError &error : errors )
139 errorMessages << error.errorString();
140
141 error( errorMessages );
142 }
143}
144#endif
145
146
147void QgsFileDownloader::error( const QStringList &errorMessages )
148{
149 for ( const QString &error : errorMessages )
150 mErrors << error;
151
152 if ( mReply )
153 mReply->abort();
154 emit downloadError( mErrors );
155}
156
157void QgsFileDownloader::error( const QString &errorMessage )
158{
159 error( QStringList() << errorMessage );
160}
161
162void QgsFileDownloader::onReadyRead()
163{
164 Q_ASSERT( mReply );
165 if ( mFile.fileName().isEmpty() )
166 {
167 error( tr( "No output filename specified" ) );
168 onFinished();
169 }
170 else if ( ! mFile.isOpen() && ! mFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
171 {
172 error( tr( "Cannot open output file: %1" ).arg( mFile.fileName() ) );
173 onFinished();
174 }
175 else
176 {
177 const QByteArray data = mReply->readAll();
178 mFile.write( data );
179 }
180}
181
182void QgsFileDownloader::onFinished()
183{
184 // when canceled
185 if ( ! mErrors.isEmpty() || mDownloadCanceled )
186 {
187 if ( mFile.isOpen() )
188 mFile.close();
189 if ( mFile.exists() )
190 mFile.remove();
191 }
192 else
193 {
194 // download finished normally
195 if ( mFile.isOpen() )
196 {
197 mFile.flush();
198 mFile.close();
199 }
200
201 if ( mReply->error() )
202 {
203 mFile.remove();
204 error( tr( "Download failed: %1" ).arg( mReply->errorString() ) );
205 }
206 else
207 {
208 emit downloadCompleted( mReply->url() );
209 }
210 }
211 emit downloadExited();
212 this->deleteLater();
213}
214
215
216void QgsFileDownloader::onDownloadProgress( qint64 bytesReceived, qint64 bytesTotal )
217{
218 if ( mDownloadCanceled )
219 {
220 return;
221 }
222 emit downloadProgress( bytesReceived, bytesTotal );
223}
224
HttpMethod
Different methods of HTTP requests.
Definition qgis.h:1056
@ Post
POST method.
Definition qgis.h:1058
@ Head
HEAD method.
Definition qgis.h:1059
@ Get
GET method.
Definition qgis.h:1057
@ Put
PUT method.
Definition qgis.h:1060
@ Delete
DELETE method.
Definition qgis.h:1061
static QgsAuthManager * authManager()
Returns the application's authentication manager instance.
bool updateNetworkRequest(QNetworkRequest &request, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkRequest with an authentication config.
bool updateNetworkReply(QNetworkReply *reply, const QString &authcfg, const QString &dataprovider=QString())
Provider call to update a QNetworkReply with an authentication config (used to skip known SSL errors,...
void cancelDownload()
Call to abort the download and delete this object after the cancellation has been processed.
void downloadExited()
Emitted always when the downloader exits.
void downloadCanceled()
Emitted when the download was canceled by the user.
void downloadError(QStringList errorMessages)
Emitted when an error makes the download fail.
void startDownload()
Called to start the download.
QgsFileDownloader(const QUrl &url, const QString &outputFileName, const QString &authcfg=QString(), bool delayStart=false, Qgis::HttpMethod httpMethod=Qgis::HttpMethod::Get, const QByteArray &data=QByteArray())
QgsFileDownloader.
void downloadCompleted(const QUrl &url)
Emitted when the download has completed successfully.
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
Emitted when data are ready to be processed.
QNetworkAccessManager with additional QGIS specific logic.
static QgsNetworkAccessManager * instance(Qt::ConnectionType connectionType=Qt::BlockingQueuedConnection)
Returns a pointer to the active QgsNetworkAccessManager for the current thread.
void requestTimedOut(QgsNetworkRequestParameters request)
Emitted when a network request has timed out.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7091
#define QgsDebugError(str)
Definition qgslogger.h:59
#define QgsSetRequestInitiatorClass(request, _class)