Skip to content

Commit

Permalink
[processing] Fix file download algorithm's temporary file missing pro…
Browse files Browse the repository at this point in the history
…per extension
  • Loading branch information
nirvn authored and nyalldawson committed Jan 17, 2021
1 parent 41ffc4c commit ab0eba2
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 2 deletions.
9 changes: 8 additions & 1 deletion python/core/auto_generated/network/qgsfiledownloader.sip.in
Expand Up @@ -38,7 +38,7 @@ An optional authentication configuration can be specified.
%Docstring
QgsFileDownloader

:param url: the download url
:param url: the download URL
:param outputFileName: file name where the downloaded content will be stored
:param authcfg: optionally apply this authentication configuration
:param delayStart: if ``True``, the download will not be commenced immediately and must
Expand All @@ -47,6 +47,13 @@ QgsFileDownloader
signals before these connections have been made.
%End

const QUrl downloadedUrl() const;
%Docstring
Returns the downloaded URL, which can differ from the original URL if redirects occurred.

.. versionadded:: 3.18
%End

signals:
void downloadCompleted();
%Docstring
Expand Down
15 changes: 15 additions & 0 deletions src/analysis/processing/qgsalgorithmfiledownloader.cpp
Expand Up @@ -93,6 +93,21 @@ QVariantMap QgsFileDownloaderAlgorithm::processAlgorithm( const QVariantMap &par
if ( !feedback->isCanceled() && !exists )
throw QgsProcessingException( tr( "Output file doesn't exist." ) );

if ( outputFile.startsWith( QgsProcessingUtils::tempFolder() ) )
{
// the output is temporary and its file name automatically generated, try to add a file extension
const QString downloadedUrl = downloader->downloadedUrl().toDisplayString();
const int length = downloadedUrl.size();
const int lastDotIndex = downloadedUrl.lastIndexOf( "." );
const int lastSlashIndex = downloadedUrl.lastIndexOf( "/" );
if ( lastDotIndex > -1 && lastDotIndex > lastSlashIndex && length - lastDotIndex <= 6 )
{
QFile tmpFile( outputFile );
tmpFile.rename( tmpFile.fileName() + downloadedUrl.mid( lastDotIndex ) );
outputFile += downloadedUrl.mid( lastDotIndex );
}
}

QVariantMap outputs;
outputs.insert( QStringLiteral( "OUTPUT" ), exists ? outputFile : QString() );
return outputs;
Expand Down
4 changes: 4 additions & 0 deletions src/core/network/qgsfiledownloader.cpp
Expand Up @@ -45,6 +45,10 @@ QgsFileDownloader::~QgsFileDownloader()
}
}

const QUrl QgsFileDownloader::downloadedUrl() const
{
return mReply ? mReply->url() : QUrl();
}

void QgsFileDownloader::startDownload()
{
Expand Down
8 changes: 7 additions & 1 deletion src/core/network/qgsfiledownloader.h
Expand Up @@ -47,7 +47,7 @@ class CORE_EXPORT QgsFileDownloader : public QObject

/**
* QgsFileDownloader
* \param url the download url
* \param url the download URL
* \param outputFileName file name where the downloaded content will be stored
* \param authcfg optionally apply this authentication configuration
* \param delayStart if TRUE, the download will not be commenced immediately and must
Expand All @@ -57,6 +57,12 @@ class CORE_EXPORT QgsFileDownloader : public QObject
*/
QgsFileDownloader( const QUrl &url, const QString &outputFileName, const QString &authcfg = QString(), bool delayStart = false );

/**
* Returns the downloaded URL, which can differ from the original URL if redirects occurred.
* \since QGIS 3.18
*/
const QUrl downloadedUrl() const;

signals:
//! Emitted when the download has completed successfully
void downloadCompleted();
Expand Down
22 changes: 22 additions & 0 deletions tests/src/analysis/testqgsprocessingalgs.cpp
Expand Up @@ -176,6 +176,8 @@ class TestQgsProcessingAlgs: public QObject
void exportMeshCrossSection();
void exportMeshTimeSeries();

void fileDownloader();

private:

bool imageCheck( const QString &testName, const QString &renderedImage );
Expand Down Expand Up @@ -6466,6 +6468,26 @@ void TestQgsProcessingAlgs::exportMeshCrossSection()
QVERIFY( i == expectedLines.count() );
}

void TestQgsProcessingAlgs::fileDownloader()
{
std::unique_ptr< QgsProcessingAlgorithm > alg( QgsApplication::processingRegistry()->createAlgorithmById( QStringLiteral( "native:filedownloader" ) ) );
QVERIFY( alg != nullptr );

QVariantMap parameters;
parameters.insert( QStringLiteral( "URL" ), QStringLiteral( "https://version.qgis.org/version.txt" ) );
parameters.insert( QStringLiteral( "OUTPUT" ), QgsProcessing::TEMPORARY_OUTPUT );

std::unique_ptr< QgsProcessingContext > context = qgis::make_unique< QgsProcessingContext >();
QgsProcessingFeedback feedback;
QVariantMap results;
bool ok = false;

results = alg->run( parameters, *context, &feedback, &ok );
QVERIFY( ok );
// verify that temporary outputs have the URL file extension appended
QVERIFY( results.value( QStringLiteral( "OUTPUT" ) ).toString().endsWith( QStringLiteral( ".txt" ) ) );
}

void TestQgsProcessingAlgs::exportMeshTimeSeries()
{
std::unique_ptr< QgsProcessingAlgorithm > alg( QgsApplication::processingRegistry()->createAlgorithmById( QStringLiteral( "native:meshexporttimeseries" ) ) );
Expand Down

0 comments on commit ab0eba2

Please sign in to comment.