QGIS API Documentation 3.99.0-Master (26c88405ac0)
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
29#include "moc_qgsfiledownloader.cpp"
30
31#ifndef QT_NO_SSL
32#include <QSslError>
33#endif
34
35QgsFileDownloader::QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg, bool delayStart, Qgis::HttpMethod httpMethod, const QByteArray &data )
36 : mUrl( url )
37 , mDownloadCanceled( false )
38 , mHttpMethod( httpMethod )
39 , mData( data )
40{
41 if ( !outputFileName.isEmpty() )
42 mFile.setFileName( outputFileName );
43 mAuthCfg = authcfg;
44 if ( !delayStart )
46}
47
48
50{
51 if ( mReply )
52 {
53 mReply->abort();
54 mReply->deleteLater();
55 }
56}
57
59{
61
62 QNetworkRequest request( mUrl );
63 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy );
64 QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsFileDownloader" ) );
65 if ( !mAuthCfg.isEmpty() )
66 {
68 }
69
70 if ( mReply )
71 {
72 disconnect( mReply, &QNetworkReply::readyRead, this, &QgsFileDownloader::onReadyRead );
73 disconnect( mReply, &QNetworkReply::finished, this, &QgsFileDownloader::onFinished );
74 disconnect( mReply, &QNetworkReply::downloadProgress, this, &QgsFileDownloader::onDownloadProgress );
75 mReply->abort();
76 mReply->deleteLater();
77 }
78
79 switch ( mHttpMethod )
80 {
82 {
83 mReply = nam->get( request );
84 break;
85 }
87 {
88 mReply = nam->post( request, mData );
89 break;
90 }
91
95 QgsDebugError( QStringLiteral( "Unsupported HTTP method: %1" ).arg( qgsEnumValueToKey( mHttpMethod ) ) );
96 // not supported
97 break;
98 }
99
100 if ( !mAuthCfg.isEmpty() )
101 {
102 QgsApplication::authManager()->updateNetworkReply( mReply, mAuthCfg );
103 }
104
105 connect( mReply, &QNetworkReply::readyRead, this, &QgsFileDownloader::onReadyRead );
106 connect( mReply, &QNetworkReply::finished, this, &QgsFileDownloader::onFinished );
107 connect( mReply, &QNetworkReply::downloadProgress, this, &QgsFileDownloader::onDownloadProgress );
108 connect( nam, qOverload< QNetworkReply *>( &QgsNetworkAccessManager::requestTimedOut ), this, &QgsFileDownloader::onRequestTimedOut, Qt::UniqueConnection );
109#ifndef QT_NO_SSL
110 connect( nam, &QgsNetworkAccessManager::sslErrors, this, &QgsFileDownloader::onSslErrors, Qt::UniqueConnection );
111#endif
112}
113
115{
116 mDownloadCanceled = true;
117 emit downloadCanceled();
118 onFinished();
119}
120
121void QgsFileDownloader::onRequestTimedOut( QNetworkReply *reply )
122{
123 if ( reply == mReply )
124 error( tr( "Network request %1 timed out" ).arg( mUrl.toString() ) );
125}
126
127#ifndef QT_NO_SSL
128void QgsFileDownloader::onSslErrors( QNetworkReply *reply, const QList<QSslError> &errors )
129{
130 if ( reply == mReply )
131 {
132 QStringList errorMessages;
133 errorMessages.reserve( errors.size() + 1 );
134 errorMessages << QStringLiteral( "SSL Errors: " );
135
136 for ( const QSslError &error : errors )
137 errorMessages << error.errorString();
138
139 error( errorMessages );
140 }
141}
142#endif
143
144
145void QgsFileDownloader::error( const QStringList &errorMessages )
146{
147 for ( const QString &error : errorMessages )
148 mErrors << error;
149
150 if ( mReply )
151 mReply->abort();
152 emit downloadError( mErrors );
153}
154
155void QgsFileDownloader::error( const QString &errorMessage )
156{
157 error( QStringList() << errorMessage );
158}
159
160void QgsFileDownloader::onReadyRead()
161{
162 Q_ASSERT( mReply );
163 if ( mFile.fileName().isEmpty() )
164 {
165 error( tr( "No output filename specified" ) );
166 onFinished();
167 }
168 else if ( ! mFile.isOpen() && ! mFile.open( QIODevice::WriteOnly | QIODevice::Truncate ) )
169 {
170 error( tr( "Cannot open output file: %1" ).arg( mFile.fileName() ) );
171 onFinished();
172 }
173 else
174 {
175 const QByteArray data = mReply->readAll();
176 mFile.write( data );
177 }
178}
179
180void QgsFileDownloader::onFinished()
181{
182 // when canceled
183 if ( ! mErrors.isEmpty() || mDownloadCanceled )
184 {
185 if ( mFile.isOpen() )
186 mFile.close();
187 if ( mFile.exists() )
188 mFile.remove();
189 }
190 else
191 {
192 // download finished normally
193 if ( mFile.isOpen() )
194 {
195 mFile.flush();
196 mFile.close();
197 }
198
199 if ( mReply->error() )
200 {
201 mFile.remove();
202 error( tr( "Download failed: %1" ).arg( mReply->errorString() ) );
203 }
204 else
205 {
206 emit downloadCompleted( mReply->url() );
207 }
208 }
209 emit downloadExited();
210 this->deleteLater();
211}
212
213
214void QgsFileDownloader::onDownloadProgress( qint64 bytesReceived, qint64 bytesTotal )
215{
216 if ( mDownloadCanceled )
217 {
218 return;
219 }
220 emit downloadProgress( bytesReceived, bytesTotal );
221}
222
HttpMethod
Different methods of HTTP requests.
Definition qgis.h:1037
@ Post
POST method.
Definition qgis.h:1039
@ Head
HEAD method.
Definition qgis.h:1040
@ Get
GET method.
Definition qgis.h:1038
@ Put
PUT method.
Definition qgis.h:1041
@ Delete
DELETE method.
Definition qgis.h:1042
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:6798
#define QgsDebugError(str)
Definition qgslogger.h:57
#define QgsSetRequestInitiatorClass(request, _class)