Skip to content

Commit

Permalink
Add a POST parameter in the FileDownloader processing algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustry authored and nyalldawson committed Sep 3, 2021
1 parent 5c9a414 commit 8b18399
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 5 deletions.
1 change: 1 addition & 0 deletions python/core/auto_additions/qgis.py
Expand Up @@ -276,6 +276,7 @@
Qgis.BrowserDirectoryMonitoring.__doc__ = 'Browser directory item monitoring switches.\n\n.. versionadded:: 3.20\n\n' + '* ``Default``: ' + Qgis.BrowserDirectoryMonitoring.Default.__doc__ + '\n' + '* ``NeverMonitor``: ' + Qgis.BrowserDirectoryMonitoring.NeverMonitor.__doc__ + '\n' + '* ``AlwaysMonitor``: ' + Qgis.BrowserDirectoryMonitoring.AlwaysMonitor.__doc__
# --
Qgis.BrowserDirectoryMonitoring.baseClass = Qgis
Qgis.HttpMethod.baseClass = Qgis
QgsVectorLayerExporter.ExportError = Qgis.VectorExportResult
# monkey patching scoped based enum
QgsVectorLayerExporter.NoError = Qgis.VectorExportResult.Success
Expand Down
4 changes: 3 additions & 1 deletion python/core/auto_generated/network/qgsfiledownloader.sip.in
Expand Up @@ -35,7 +35,7 @@ An optional authentication configuration can be specified.
%End
public:

QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg = QString(), bool delayStart = false );
QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg = QString(), bool delayStart = false, Qgis::HttpMethod httpMethod = Qgis::HttpMethod::Get, const QByteArray &data = QByteArray() );
%Docstring
QgsFileDownloader

Expand All @@ -46,6 +46,8 @@ QgsFileDownloader
be triggered by a later call to :py:func:`~QgsFileDownloader.startDownload`. This can be useful if connections need
to be made to the downloader and there's a chance the download will emit
signals before these connections have been made.
:param httpMethod: Method for the HTTP request : GET or POST, since QGIS 3.22
:param data: If the request is POST, some data can be added, since QGIS 3.22
%End

signals:
Expand Down
6 changes: 6 additions & 0 deletions python/core/auto_generated/qgis.sip.in
Expand Up @@ -211,6 +211,12 @@ The development version
AlwaysMonitor,
};

enum HttpMethod
{
Get,
Post
};

enum class VectorExportResult
{
Success,
Expand Down
36 changes: 35 additions & 1 deletion src/analysis/processing/qgsalgorithmfiledownloader.cpp
Expand Up @@ -16,8 +16,11 @@
***************************************************************************/

#include "qgsalgorithmfiledownloader.h"
#include "qgsprocessingparameters.h"
#include "qgis.h"
#include "qgsfiledownloader.h"
#include "qgsfileutils.h"

#include <QEventLoop>
#include <QFileInfo>
#include <QTimer>
Expand Down Expand Up @@ -63,6 +66,26 @@ QgsFileDownloaderAlgorithm *QgsFileDownloaderAlgorithm::createInstance() const
void QgsFileDownloaderAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterString( QStringLiteral( "URL" ), tr( "URL" ), QVariant(), false, false ) );

std::unique_ptr< QgsProcessingParameterEnum > methodParam = std::make_unique < QgsProcessingParameterEnum > (
QStringLiteral( "METHOD" ),
QObject::tr( "Method" ),
QStringList()
<< QObject::tr( "GET" )
<< QObject::tr( "POST" ),
false,
QStringLiteral( "GET" )
);
methodParam->setHelp( QObject::tr( "The HTTP method to use for the request" ) );
methodParam->setFlags( methodParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( methodParam.release() );

std::unique_ptr< QgsProcessingParameterString > dataParam = std::make_unique < QgsProcessingParameterString >(
QStringLiteral( "DATA" ), tr( "Data" ), QVariant(), false, true );
dataParam->setHelp( QObject::tr( "The data to add in the body if the request is a POST" ) );
dataParam->setFlags( dataParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( dataParam.release() );

addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ),
tr( "File destination" ), QObject::tr( "All files (*.*)" ), QVariant(), true ) );
}
Expand All @@ -73,13 +96,24 @@ QVariantMap QgsFileDownloaderAlgorithm::processAlgorithm( const QVariantMap &par
QString url = parameterAsString( parameters, QStringLiteral( "URL" ), context );
if ( url.isEmpty() )
throw QgsProcessingException( tr( "No URL specified" ) );

QString data = parameterAsString( parameters, QStringLiteral( "DATA" ), context );
QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context );

QEventLoop loop;
QTimer timer;
QUrl downloadedUrl;
QStringList errors;
QgsFileDownloader *downloader = new QgsFileDownloader( QUrl( url ), outputFile, QString(), true );

Qgis::HttpMethod httpMethod = static_cast< Qgis::HttpMethod>( parameterAsEnum( parameters, QStringLiteral( "METHOD" ), context ) );

if ( httpMethod == Qgis::HttpMethod::Get && ! data.isEmpty() )
{
feedback->pushWarning( tr( "DATA parameter is not used when it's a GET request." ) );
data = QString();
}

QgsFileDownloader *downloader = new QgsFileDownloader( QUrl( url ), outputFile, QString(), true, httpMethod, data.toUtf8() );
connect( mFeedback, &QgsFeedback::canceled, downloader, &QgsFileDownloader::cancelDownload );
connect( downloader, &QgsFileDownloader::downloadError, this, [&errors, &loop]( const QStringList & e ) { errors = e; loop.exit(); } );
connect( downloader, &QgsFileDownloader::downloadProgress, this, &QgsFileDownloaderAlgorithm::receiveProgressFromDownloader );
Expand Down
19 changes: 17 additions & 2 deletions src/core/network/qgsfiledownloader.cpp
Expand Up @@ -25,9 +25,11 @@
#include <QSslError>
#endif

QgsFileDownloader::QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg, bool delayStart )
QgsFileDownloader::QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg, bool delayStart, Qgis::HttpMethod httpMethod, const QByteArray &data )
: mUrl( url )
, mDownloadCanceled( false )
, mHttpMethod( httpMethod )
, mData( data )
{
mFile.setFileName( outputFileName );
mAuthCfg = authcfg;
Expand Down Expand Up @@ -65,7 +67,20 @@ void QgsFileDownloader::startDownload()
mReply->deleteLater();
}

mReply = nam->get( request );
switch ( mHttpMethod )
{
case Qgis::HttpMethod::Get:
{
mReply = nam->get( request );
break;
}
case Qgis::HttpMethod::Post:
{
mReply = nam->post( request, mData );
break;
}
}

if ( !mAuthCfg.isEmpty() )
{
QgsApplication::authManager()->updateNetworkReply( mReply, mAuthCfg );
Expand Down
7 changes: 6 additions & 1 deletion src/core/network/qgsfiledownloader.h
Expand Up @@ -21,6 +21,7 @@
#include <QNetworkReply>
#include <QUrl>

#include "qgis.h"
#include "qgis_core.h"

#ifndef QT_NO_SSL
Expand Down Expand Up @@ -56,8 +57,10 @@ class CORE_EXPORT QgsFileDownloader : public QObject
* be triggered by a later call to startDownload(). This can be useful if connections need
* to be made to the downloader and there's a chance the download will emit
* signals before these connections have been made.
* \param httpMethod Method for the HTTP request : GET or POST, since QGIS 3.22
* \param data If the request is POST, some data can be added, since QGIS 3.22
*/
QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg = QString(), bool delayStart = false );
QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg = QString(), bool delayStart = false, Qgis::HttpMethod httpMethod = Qgis::HttpMethod::Get, const QByteArray &data = QByteArray() );

signals:
//! Emitted when the download has completed successfully
Expand Down Expand Up @@ -123,6 +126,8 @@ class CORE_EXPORT QgsFileDownloader : public QObject
QNetworkReply *mReply = nullptr;
QFile mFile;
bool mDownloadCanceled;
Qgis::HttpMethod mHttpMethod = Qgis::HttpMethod::Get;
QByteArray mData;
QStringList mErrors;
QString mAuthCfg;
};
Expand Down
11 changes: 11 additions & 0 deletions src/core/qgis.h
Expand Up @@ -309,6 +309,17 @@ class CORE_EXPORT Qgis
};
Q_ENUM( BrowserDirectoryMonitoring )

/**
* Different methods of HTTP requests
* \since 3.22
*/
enum HttpMethod
{
Get = 0, //!< GET method
Post = 1 //!< POST method
};
Q_ENUM( HttpMethod )

/**
* Vector layer export result codes.
*
Expand Down

0 comments on commit 8b18399

Please sign in to comment.