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