QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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#include <QString>
29
30using namespace Qt::StringLiterals;
31
33
34QgsHttpExternalStorageStoreTask::QgsHttpExternalStorageStoreTask( const QUrl &url, const QString &filePath, const QString &authCfg )
35 : QgsTask( tr( "Storing %1" ).arg( QFileInfo( filePath ).baseName() ) )
36 , mUrl( url )
37 , mFilePath( filePath )
38 , mAuthCfg( authCfg )
39 , mFeedback( std::make_unique<QgsFeedback>( this ) )
40{}
41
42QgsHttpExternalStorageStoreTask::~QgsHttpExternalStorageStoreTask() = default;
43
44bool QgsHttpExternalStorageStoreTask::run()
45{
47 request.setAuthCfg( mAuthCfg );
48
49 QNetworkRequest req( mUrl );
50 QgsSetRequestInitiatorClass( req, u"QgsHttpExternalStorageStoreTask"_s );
51
52 QFile f( mFilePath );
53 if ( !f.open( QIODevice::ReadOnly ) )
54 return false;
55
56 if ( mPrepareRequestHandler )
57 mPrepareRequestHandler( req, &f );
58
59 connect( &request, &QgsBlockingNetworkRequest::uploadProgress, this, [this]( qint64 bytesReceived, qint64 bytesTotal ) {
60 if ( !isCanceled() && bytesTotal > 0 )
61 {
62 const int progress = ( bytesReceived * 100 ) / bytesTotal;
63 setProgress( progress );
64 }
65 } );
66
67 QgsBlockingNetworkRequest::ErrorCode err = request.put( req, &f, mFeedback.get() );
68
70 {
71 mErrorString = request.errorMessage();
72 }
73
74 return !isCanceled() && err == QgsBlockingNetworkRequest::NoError;
75}
76
77void QgsHttpExternalStorageStoreTask::cancel()
78{
79 mFeedback->cancel();
81}
82
83QString QgsHttpExternalStorageStoreTask::errorString() const
84{
85 return mErrorString;
86}
87
88void QgsHttpExternalStorageStoreTask::setPrepareRequestHandler( std::function< void( QNetworkRequest &request, QFile *f ) > handler )
89{
90 mPrepareRequestHandler = std::move( handler );
91}
92
93QgsHttpExternalStorageStoredContent::QgsHttpExternalStorageStoredContent( const QString &filePath, const QString &url, const QString &authcfg )
94{
95 QString storageUrl = url;
96 if ( storageUrl.endsWith( "/" ) )
97 storageUrl.append( QFileInfo( filePath ).fileName() );
98
99 mUploadTask = new QgsHttpExternalStorageStoreTask( storageUrl, filePath, authcfg );
100
101 connect( mUploadTask, &QgsTask::taskCompleted, this, [this, storageUrl] {
102 mUrl = storageUrl;
104 emit stored();
105 } );
106
107 connect( mUploadTask, &QgsTask::taskTerminated, this, [this] { reportError( mUploadTask->errorString() ); } );
108
109 connect( mUploadTask, &QgsTask::progressChanged, this, [this]( double progress ) { emit progressChanged( progress ); } );
110}
111
112void QgsHttpExternalStorageStoredContent::store()
113{
114 setStatus( Qgis::ContentStatus::Running );
115 QgsApplication::taskManager()->addTask( mUploadTask );
116}
117
118
119void QgsHttpExternalStorageStoredContent::cancel()
120{
121 if ( !mUploadTask )
122 return;
123
124 disconnect( mUploadTask, &QgsTask::taskTerminated, this, nullptr );
125 connect( mUploadTask, &QgsTask::taskTerminated, this, [this] {
127 emit canceled();
128 } );
129
130 mUploadTask->cancel();
131}
132
133QString QgsHttpExternalStorageStoredContent::url() const
134{
135 return mUrl;
136}
137
138void QgsHttpExternalStorageStoredContent::setPrepareRequestHandler( std::function< void( QNetworkRequest &request, QFile *f ) > handler )
139{
140 mUploadTask->setPrepareRequestHandler( std::move( handler ) );
141}
142
143
144QgsHttpExternalStorageFetchedContent::QgsHttpExternalStorageFetchedContent( QgsFetchedContent *fetchedContent )
145 : mFetchedContent( fetchedContent )
146{
147 connect( mFetchedContent, &QgsFetchedContent::fetched, this, &QgsHttpExternalStorageFetchedContent::onFetched );
148 connect( mFetchedContent, &QgsFetchedContent::errorOccurred, this, [this]( QNetworkReply::NetworkError code, const QString &errorMsg ) {
149 Q_UNUSED( code );
150 reportError( errorMsg );
151 } );
152}
153
154void QgsHttpExternalStorageFetchedContent::fetch()
155{
156 if ( !mFetchedContent )
157 return;
158
159 setStatus( Qgis::ContentStatus::Running );
160 mFetchedContent->download();
161
162 // could be already fetched/cached
163 if ( mFetchedContent->status() == QgsFetchedContent::Finished )
164 {
166 emit fetched();
167 }
168}
169
170QString QgsHttpExternalStorageFetchedContent::filePath() const
171{
172 return mFetchedContent ? mFetchedContent->filePath() : QString();
173}
174
175void QgsHttpExternalStorageFetchedContent::onFetched()
176{
177 if ( !mFetchedContent )
178 return;
179
180 if ( mFetchedContent->status() == QgsFetchedContent::Finished )
181 {
183 emit fetched();
184 }
185}
186
187void QgsHttpExternalStorageFetchedContent::cancel()
188{
189 mFetchedContent->cancel();
190}
191
192
193// WEB DAV PROTOCOL
194
195QString QgsWebDavExternalStorage::type() const
196{
197 return u"WebDAV"_s;
198};
199
200QString QgsWebDavExternalStorage::displayName() const
201{
202 return QObject::tr( "WebDAV Storage" );
203};
204
205QgsExternalStorageStoredContent *QgsWebDavExternalStorage::doStore( const QString &filePath, const QString &url, const QString &authcfg ) const
206{
207 return new QgsHttpExternalStorageStoredContent( filePath, url, authcfg );
208};
209
210QgsExternalStorageFetchedContent *QgsWebDavExternalStorage::doFetch( const QString &url, const QString &authConfig ) const
211{
213
214 return new QgsHttpExternalStorageFetchedContent( fetchedContent );
215}
216
217
218// AWS S3 PROTOCOL
219
220QString QgsAwsS3ExternalStorage::type() const
221{
222 return u"AWSS3"_s;
223};
224
225QString QgsAwsS3ExternalStorage::displayName() const
226{
227 return QObject::tr( "AWS S3" );
228};
229
230QgsExternalStorageStoredContent *QgsAwsS3ExternalStorage::doStore( const QString &filePath, const QString &url, const QString &authcfg ) const
231{
232 auto storedContent = std::make_unique<QgsHttpExternalStorageStoredContent>( filePath, url, authcfg );
233 storedContent->setPrepareRequestHandler( []( QNetworkRequest &request, QFile *f ) {
234 QCryptographicHash payloadCrypto( QCryptographicHash::Sha256 );
235 payloadCrypto.addData( f );
236 QByteArray payloadHash = payloadCrypto.result().toHex();
237 f->seek( 0 );
238 request.setRawHeader( QByteArray( "X-Amz-Content-SHA256" ), payloadHash );
239 } );
240
241 return storedContent.release();
242};
243
244QgsExternalStorageFetchedContent *QgsAwsS3ExternalStorage::doFetch( const QString &url, const QString &authConfig ) const
245{
247
248 return new QgsHttpExternalStorageFetchedContent( fetchedContent );
249}
@ Canceled
Content fetching/storing has been canceled.
Definition qgis.h:1929
@ Running
Content fetching/storing is in progress.
Definition qgis.h:1926
@ Finished
Content fetching/storing is finished and successful.
Definition qgis.h:1927
@ Deferred
Do not start immediately the action.
Definition qgis.h:1170
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(), const QgsHttpHeaders &headers=QgsHttpHeaders())
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)