QGIS API Documentation 3.99.0-Master (a8882ad4560)
Loading...
Searching...
No Matches
qgshttpexternalstorage.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgswebdavexternalstorage.cpp
3 --------------------------------------
4 Date : March 2021
5 Copyright : (C) 2021 by Julien Cabieces
6 Email : julien dot cabieces at oslandia 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 "qgsapplication.h"
18#include "qgsfeedback.h"
23
24#include <QCryptographicHash>
25#include <QFile>
26#include <QFileInfo>
27#include <QPointer>
28
30
31QgsHttpExternalStorageStoreTask::QgsHttpExternalStorageStoreTask( const QUrl &url, const QString &filePath, const QString &authCfg )
32 : QgsTask( tr( "Storing %1" ).arg( QFileInfo( filePath ).baseName() ) )
33 , mUrl( url )
34 , mFilePath( filePath )
35 , mAuthCfg( authCfg )
36 , mFeedback( std::make_unique<QgsFeedback>( this ) )
37{
38}
39
40QgsHttpExternalStorageStoreTask::~QgsHttpExternalStorageStoreTask() = default;
41
42bool QgsHttpExternalStorageStoreTask::run()
43{
45 request.setAuthCfg( mAuthCfg );
46
47 QNetworkRequest req( mUrl );
48 QgsSetRequestInitiatorClass( req, u"QgsHttpExternalStorageStoreTask"_s );
49
50 QFile f( mFilePath );
51 if ( !f.open( QIODevice::ReadOnly ) )
52 return false;
53
54 if ( mPrepareRequestHandler )
55 mPrepareRequestHandler( req, &f );
56
57 connect( &request, &QgsBlockingNetworkRequest::uploadProgress, this, [this]( qint64 bytesReceived, qint64 bytesTotal )
58 {
59 if ( !isCanceled() && bytesTotal > 0 )
60 {
61 const int progress = ( bytesReceived * 100 ) / bytesTotal;
62 setProgress( progress );
63 }
64 } );
65
66 QgsBlockingNetworkRequest::ErrorCode err = request.put( req, &f, mFeedback.get() );
67
69 {
70 mErrorString = request.errorMessage();
71 }
72
73 return !isCanceled() && err == QgsBlockingNetworkRequest::NoError;
74}
75
76void QgsHttpExternalStorageStoreTask::cancel()
77{
78 mFeedback->cancel();
80}
81
82QString QgsHttpExternalStorageStoreTask::errorString() const
83{
84 return mErrorString;
85}
86
87void QgsHttpExternalStorageStoreTask::setPrepareRequestHandler( std::function< void( QNetworkRequest &request, QFile *f ) > handler )
88{
89 mPrepareRequestHandler = std::move( handler );
90}
91
92QgsHttpExternalStorageStoredContent::QgsHttpExternalStorageStoredContent( const QString &filePath, const QString &url, const QString &authcfg )
93{
94 QString storageUrl = url;
95 if ( storageUrl.endsWith( "/" ) )
96 storageUrl.append( QFileInfo( filePath ).fileName() );
97
98 mUploadTask = new QgsHttpExternalStorageStoreTask( storageUrl, filePath, authcfg );
99
100 connect( mUploadTask, &QgsTask::taskCompleted, this, [this, storageUrl]
101 {
102 mUrl = storageUrl;
104 emit stored();
105 } );
106
107 connect( mUploadTask, &QgsTask::taskTerminated, this, [this]
108 {
109 reportError( mUploadTask->errorString() );
110 } );
111
112 connect( mUploadTask, &QgsTask::progressChanged, this, [this]( double progress )
113 {
114 emit progressChanged( progress );
115 } );
116}
117
118void QgsHttpExternalStorageStoredContent::store()
119{
120 setStatus( Qgis::ContentStatus::Running );
121 QgsApplication::taskManager()->addTask( mUploadTask );
122}
123
124
125void QgsHttpExternalStorageStoredContent::cancel()
126{
127 if ( !mUploadTask )
128 return;
129
130 disconnect( mUploadTask, &QgsTask::taskTerminated, this, nullptr );
131 connect( mUploadTask, &QgsTask::taskTerminated, this, [this]
132 {
134 emit canceled();
135 } );
136
137 mUploadTask->cancel();
138}
139
140QString QgsHttpExternalStorageStoredContent::url() const
141{
142 return mUrl;
143}
144
145void QgsHttpExternalStorageStoredContent::setPrepareRequestHandler( std::function< void( QNetworkRequest &request, QFile *f ) > handler )
146{
147 mUploadTask->setPrepareRequestHandler( std::move( handler ) );
148}
149
150
151QgsHttpExternalStorageFetchedContent::QgsHttpExternalStorageFetchedContent( QgsFetchedContent *fetchedContent )
152 : mFetchedContent( fetchedContent )
153{
154 connect( mFetchedContent, &QgsFetchedContent::fetched, this, &QgsHttpExternalStorageFetchedContent::onFetched );
155 connect( mFetchedContent, &QgsFetchedContent::errorOccurred, this, [this]( QNetworkReply::NetworkError code, const QString & errorMsg )
156 {
157 Q_UNUSED( code );
158 reportError( errorMsg );
159 } );
160}
161
162void QgsHttpExternalStorageFetchedContent::fetch()
163{
164 if ( !mFetchedContent )
165 return;
166
167 setStatus( Qgis::ContentStatus::Running );
168 mFetchedContent->download();
169
170 // could be already fetched/cached
171 if ( mFetchedContent->status() == QgsFetchedContent::Finished )
172 {
174 emit fetched();
175 }
176}
177
178QString QgsHttpExternalStorageFetchedContent::filePath() const
179{
180 return mFetchedContent ? mFetchedContent->filePath() : QString();
181}
182
183void QgsHttpExternalStorageFetchedContent::onFetched()
184{
185 if ( !mFetchedContent )
186 return;
187
188 if ( mFetchedContent->status() == QgsFetchedContent::Finished )
189 {
191 emit fetched();
192 }
193}
194
195void QgsHttpExternalStorageFetchedContent::cancel()
196{
197 mFetchedContent->cancel();
198}
199
200
201// WEB DAV PROTOCOL
202
203QString QgsWebDavExternalStorage::type() const
204{
205 return u"WebDAV"_s;
206};
207
208QString QgsWebDavExternalStorage::displayName() const
209{
210 return QObject::tr( "WebDAV Storage" );
211};
212
213QgsExternalStorageStoredContent *QgsWebDavExternalStorage::doStore( const QString &filePath, const QString &url, const QString &authcfg ) const
214{
215 return new QgsHttpExternalStorageStoredContent( filePath, url, authcfg );
216};
217
218QgsExternalStorageFetchedContent *QgsWebDavExternalStorage::doFetch( const QString &url, const QString &authConfig ) const
219{
221
222 return new QgsHttpExternalStorageFetchedContent( fetchedContent );
223}
224
225
226// AWS S3 PROTOCOL
227
228QString QgsAwsS3ExternalStorage::type() const
229{
230 return u"AWSS3"_s;
231};
232
233QString QgsAwsS3ExternalStorage::displayName() const
234{
235 return QObject::tr( "AWS S3" );
236};
237
238QgsExternalStorageStoredContent *QgsAwsS3ExternalStorage::doStore( const QString &filePath, const QString &url, const QString &authcfg ) const
239{
240 auto storedContent = std::make_unique<QgsHttpExternalStorageStoredContent>( filePath, url, authcfg );
241 storedContent->setPrepareRequestHandler( []( QNetworkRequest & request, QFile * f )
242 {
243 QCryptographicHash payloadCrypto( QCryptographicHash::Sha256 );
244 payloadCrypto.addData( f );
245 QByteArray payloadHash = payloadCrypto.result().toHex();
246 f->seek( 0 );
247 request.setRawHeader( QByteArray( "X-Amz-Content-SHA256" ), payloadHash );
248 } );
249
250 return storedContent.release();
251};
252
253QgsExternalStorageFetchedContent *QgsAwsS3ExternalStorage::doFetch( const QString &url, const QString &authConfig ) const
254{
256
257 return new QgsHttpExternalStorageFetchedContent( fetchedContent );
258}
@ Canceled
Content fetching/storing has been canceled.
Definition qgis.h:1896
@ Running
Content fetching/storing is in progress.
Definition qgis.h:1893
@ Finished
Content fetching/storing is finished and successful.
Definition qgis.h:1894
@ Deferred
Do not start immediately the action.
Definition qgis.h:1151
static QgsNetworkContentFetcherRegistry * networkContentFetcherRegistry()
Returns the application's network content registry used for fetching temporary files during QGIS sess...
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
A thread safe class for performing blocking (sync) network requests, with full support for QGIS proxy...
ErrorCode put(QNetworkRequest &request, QIODevice *data, QgsFeedback *feedback=nullptr)
Performs a "put" operation on the specified request, using the given data.
void uploadProgress(qint64 bytesReceived, qint64 bytesTotal)
Emitted when when data are sent during a request.
void setAuthCfg(const QString &authCfg)
Sets the authentication config id which should be used during the request.
QString errorMessage() const
Returns the error message string, after a get(), post(), head() or put() request has been made.
@ NoError
No error was encountered.
Abstract base class for QgsExternalStorage fetched content.
Abstract base class for QgsExternalStorage stored content.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition qgsfeedback.h:44
Holds information about fetched network content.
void errorOccurred(QNetworkReply::NetworkError code, const QString &errorMsg)
Emitted when an error with code error occurred while processing the request errorMsg is a textual des...
@ Finished
Download finished and successful.
void fetched()
Emitted when the file is fetched and accessible.
QgsFetchedContent * fetch(const QString &url, Qgis::ActionStart fetchingMode=Qgis::ActionStart::Deferred, const QString &authConfig=QString())
Initialize a download for the given URL.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
Abstract base class for long running background tasks.
void taskCompleted()
Will be emitted by task to indicate its successful completion.
void progressChanged(double progress)
Will be emitted by task when its progress changes.
virtual void cancel()
Notifies the task that it should terminate.
void taskTerminated()
Will be emitted by task if it has terminated for any reason other then completion (e....
#define QgsSetRequestInitiatorClass(request, _class)