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