QGIS API Documentation  3.0.2-Girona (307d082)
qgsalgorithmfiledownloader.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmfiledownloader.cpp
3  ---------------------
4  begin : October 2017
5  copyright : (C) 2017 by Etienne Trimaille
6  email : etienne at kartoza dot com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
19 #include "qgsfiledownloader.h"
20 #include "qgsfileutils.h"
21 #include <QEventLoop>
22 #include <QFileInfo>
23 #include <QTimer>
24 #include <QUrl>
25 
27 
28 QString QgsFileDownloaderAlgorithm::name() const
29 {
30  return QStringLiteral( "filedownloader" );
31 }
32 
33 QString QgsFileDownloaderAlgorithm::displayName() const
34 {
35  return tr( "Download file" );
36 }
37 
38 QStringList QgsFileDownloaderAlgorithm::tags() const
39 {
40  return tr( "file,downloader,internet,url,fetch,get,https" ).split( ',' );
41 }
42 
43 QString QgsFileDownloaderAlgorithm::group() const
44 {
45  return tr( "File tools" );
46 }
47 
48 QString QgsFileDownloaderAlgorithm::groupId() const
49 {
50  return QStringLiteral( "filetools" );
51 }
52 
53 QString QgsFileDownloaderAlgorithm::shortHelpString() const
54 {
55  return tr( "This algorithm downloads a URL on the file system." );
56 }
57 
58 QgsFileDownloaderAlgorithm *QgsFileDownloaderAlgorithm::createInstance() const
59 {
60  return new QgsFileDownloaderAlgorithm();
61 }
62 
63 void QgsFileDownloaderAlgorithm::initAlgorithm( const QVariantMap & )
64 {
65  addParameter( new QgsProcessingParameterString( QStringLiteral( "URL" ), tr( "URL" ), QVariant(), false, false ) );
66  addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ),
67  tr( "File destination" ), QObject::tr( "All files (*.*)" ), QVariant(), true ) );
68 }
69 
70 QVariantMap QgsFileDownloaderAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
71 {
72  mFeedback = feedback;
73  QString url = parameterAsString( parameters, QStringLiteral( "URL" ), context );
74  QString outputFile = parameterAsFileOutput( parameters, QStringLiteral( "OUTPUT" ), context );
75 
76  QEventLoop loop;
77  QTimer timer;
78  QgsFileDownloader *downloader = new QgsFileDownloader( QUrl( url ), outputFile, QString(), true );
79  connect( mFeedback, &QgsFeedback::canceled, downloader, &QgsFileDownloader::cancelDownload );
80  connect( downloader, &QgsFileDownloader::downloadError, this, &QgsFileDownloaderAlgorithm::reportErrors );
81  connect( downloader, &QgsFileDownloader::downloadProgress, this, &QgsFileDownloaderAlgorithm::receiveProgressFromDownloader );
82  connect( downloader, &QgsFileDownloader::downloadExited, &loop, &QEventLoop::quit );
83  connect( &timer, &QTimer::timeout, this, &QgsFileDownloaderAlgorithm::sendProgressFeedback );
84  downloader->startDownload();
85  timer.start( 1000 );
86 
87  loop.exec();
88 
89  timer.stop();
90  bool exists = QFileInfo::exists( outputFile );
91  if ( !feedback->isCanceled() && !exists )
92  throw QgsProcessingException( tr( "Output file doesn't exist." ) );
93 
94  QVariantMap outputs;
95  outputs.insert( QStringLiteral( "OUTPUT" ), exists ? outputFile : QString() );
96  return outputs;
97 }
98 
99 void QgsFileDownloaderAlgorithm::reportErrors( const QStringList &errors )
100 {
101  throw QgsProcessingException( errors.join( '\n' ) );
102 }
103 
104 void QgsFileDownloaderAlgorithm::sendProgressFeedback()
105 {
106  if ( !mReceived.isEmpty() && mLastReport != mReceived )
107  {
108  mLastReport = mReceived;
109  if ( mTotal.isEmpty() )
110  mFeedback->pushInfo( tr( "%1 downloaded." ).arg( mReceived ) );
111  else
112  mFeedback->pushInfo( tr( "%1 of %2 downloaded." ).arg( mReceived, mTotal ) );
113  }
114 }
115 
116 void QgsFileDownloaderAlgorithm::receiveProgressFromDownloader( qint64 bytesReceived, qint64 bytesTotal )
117 {
118  mReceived = QgsFileUtils::representFileSize( bytesReceived );
119  if ( bytesTotal > 0 )
120  {
121  if ( mTotal.isEmpty() )
122  mTotal = QgsFileUtils::representFileSize( bytesTotal );
123 
124  mFeedback->setProgress( ( bytesReceived * 100 ) / bytesTotal );
125  }
126 }
127 
void startDownload()
Called to start the download.
Base class for providing feedback from a processing algorithm.
void canceled()
Internal routines can connect to this signal if they use event loop.
static QString representFileSize(qint64 bytes)
Return the human size from bytes.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
A generic file based destination parameter, for specifying the destination path for a file (non-map l...
QgsFileDownloader is a utility class for downloading files.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
Emitted when data are ready to be processed.
void downloadError(QStringList errorMessages)
Emitted when an error makes the download fail.
Contains information about the context in which a processing algorithm is executed.
void cancelDownload()
Call to abort the download and delete this object after the cancelation has been processed.
void downloadExited()
Emitted always when the downloader exits.
A string parameter for processing algorithms.