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