Results 1 to 2 of 2

Thread: QNetworkReply signal downloadProgress returns bytesTotal incorrectly

  1. #1
    Join Date
    Jun 2011
    Location
    Cracow, Poland
    Posts
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default QNetworkReply signal downloadProgress returns bytesTotal incorrectly

    Hello!

    I am stragling with an issue with QNetworkReply. I have created my own class to manage downloading images from the Internet. It utilises QNetworkReply/QNetworkAccessManager tandem. It works fine for most of the URLs but for some does not (the problem is rather connected with hosts). E.g. http://wordpress.birds.com/wp-conten...home/bird4.jpg. The problem is that QNetworkReply class signals finished() without actually downloading proper amount of data. It corrupts any conncection. In addition, downloadProgress signal provides bytesTotal incorrectly. Returned number of bytes is 262, whilst the image is much bigger. I am using Qt 4.7.0.

    sources attached:

    Qt Code:
    1. #ifndef NETWORKIMAGE_H_
    2. #define NETWORKIMAGE_H_
    3.  
    4. #include <QUrl>
    5. #include <QString>
    6. #include <QStringList>
    7. #include <QNetworkAccessManager>
    8. #include <QNetworkReply>
    9. #include <QHostInfo>
    10. #include <QTimer>
    11. #include <QMutex>
    12.  
    13. #include <opencv/highgui.h>
    14.  
    15. class NetworkImage : public QObject{
    16. Q_OBJECT
    17. public:
    18. NetworkImage();
    19. virtual ~NetworkImage();
    20. bool download();
    21. bool setUrl(QString &);
    22. void setImageMaximumSize(qint64 &);
    23. bool isRecognisedAsValidURL();
    24. void setVerbose(bool = true);
    25. void askForIP();
    26. QStringList getIPList();
    27. void saveImage(QString &);
    28. bool isError();
    29. QString getErrorString();
    30. void setManager(QNetworkAccessManager *);
    31. private:
    32. QUrl url;
    33. QNetworkAccessManager *manager;
    34. QByteArray byteArray;
    35. qint64 imageMaximumSize;
    36. bool verbose;
    37. bool errorOccured;
    38. QString errorString;
    39. QTimer timer;
    40. QNetworkReply* reply;
    41. int progress;
    42. qint64 bytesRecievedPreviously;
    43. qint64 bytesRecieved;
    44. bool retrieved;
    45. QMutex mutex;
    46. private slots:
    47. void downloadFinished();
    48. void setIP(QHostInfo);
    49. void printProgress(qint64 bytesReceived, qint64 bytesTotal);
    50. void timerTic();
    51. signals:
    52. void error(QString);
    53. void done();
    54. IPRetrieved();
    55. };
    56.  
    57. #endif /* NETWORKIMAGE_H_ */
    To copy to clipboard, switch view to plain text mode 


    Qt Code:
    1. #include "NetworkImage.h"
    2. #include <iostream>
    3. #include <QFile>
    4. #include <QImage>
    5. #include <QSettings>
    6. #include <QMutexLocker>
    7.  
    8.  
    9. NetworkImage::NetworkImage() {
    10. // TODO Auto-generated constructor stub
    11. // Set maximum size of the image to 10MB;
    12. verbose = false;
    13. errorOccured = false;
    14. progress = 0;
    15. QSettings settings("NetworkImage.config", QSettings::IniFormat);
    16. int time = settings.value("timeToTimeout").toInt();
    17. //time = 30000;
    18. timer.setInterval(time);
    19. imageMaximumSize = settings.value("imageMaximumSize").toInt();
    20. imageMaximumSize = 10000000;
    21. bytesRecievedPreviously = 0;
    22. bytesRecieved = 0;
    23. retrieved = false;
    24. }
    25.  
    26. NetworkImage::~NetworkImage() {
    27. // TODO Auto-generated destructor stub
    28. }
    29.  
    30. bool NetworkImage::setUrl(QString & textUrl)
    31. {
    32.  
    33. url.setUrl(textUrl);
    34. if(verbose)
    35. {
    36. std::cout << "---------------------------------------------------" << std::endl;
    37. std::cout << "url : "<< url.toString().toStdString() << std::endl;
    38. std::cout << "host : "<< url.host().toStdString() << std::endl;
    39. }
    40.  
    41. if(isRecognisedAsValidURL())
    42. {
    43. return true;
    44. }
    45. else
    46. {
    47. errorOccured = true;
    48. errorString = "Error: Invalid URL";
    49. return false;
    50. }
    51.  
    52. }
    53.  
    54. bool NetworkImage::download()
    55. {
    56. if(isRecognisedAsValidURL())
    57. {
    58. reply = manager->get(QNetworkRequest(url));
    59. qDebug() << "encoding=" << reply->rawHeader( "Content-Encoding");
    60. connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
    61. connect(reply, SIGNAL(downloadProgress(qint64, qint64)),this, SLOT(printProgress(qint64, qint64)) );
    62. connect(&timer,SIGNAL(timeout()), this, SLOT(timerTic()));
    63. timer.start();
    64. askForIP();
    65. if(verbose)
    66. {
    67. std::cout << "Requesting connection..." << std::endl;
    68. }
    69. return true;
    70. }
    71. else
    72. {
    73. disconnect(reply, SIGNAL(downloadProgress(qint64, qint64)),this, SLOT(printProgress(qint64, qint64)) );
    74. emit error("Error: Invalid URL");
    75. errorOccured = true;
    76. errorString = "Error: Invalid URL";
    77.  
    78. return false;
    79. }
    80.  
    81. }
    82.  
    83. extern IplImage* qImage2IplImage(QImage& qImage);
    84. void NetworkImage::downloadFinished()
    85. {
    86. QMutexLocker locker(&mutex);
    87. retrieved = true;
    88. disconnect(&timer,SIGNAL(timeout()), this, SLOT(timerTic()));
    89. disconnect(reply, SIGNAL(downloadProgress(qint64, qint64)),this, SLOT(printProgress(qint64, qint64)) );
    90. if(reply->error() == QNetworkReply::NoError)
    91. {
    92. if(verbose)
    93. std::cout << "Download has finished" << std::endl;
    94.  
    95. byteArray = reply->read(imageMaximumSize);
    96.  
    97. emit done();
    98. //if(!cvSaveImage("output.jpg",img)) printf("Could not save: %s\n","output.jpg");
    99. }
    100. else
    101. {
    102. errorOccured = true;
    103. errorString = "Error: unknown error!";
    104.  
    105.  
    106. std::cerr << errorString.toStdString() << std::endl;
    107. std::cout << "---------------------------------------------------" << std::endl;
    108. emit error(errorString);
    109. }
    110. reply->deleteLater();
    111. //manager->deleteLater();
    112. return;
    113. }
    114.  
    115. void NetworkImage::setImageMaximumSize(qint64 & x)
    116. {
    117. imageMaximumSize = x;
    118. }
    119.  
    120. bool NetworkImage::isRecognisedAsValidURL()
    121. {
    122. if(url.path().isEmpty())
    123. {
    124. std::cerr << "Error: Invalid URL!" << std::endl;
    125. return false;
    126. }
    127. else if(!url.isValid())
    128. {
    129. std::cerr << "Error: Invalid URL!" << std::endl;
    130. return false;
    131. }
    132. else if( (url.scheme() != "http") && (url.scheme() != "https") )
    133. {
    134. std::cerr << "Error: Invalid URL!" << std::endl;
    135. return false;
    136. }
    137. else if(url.host().isEmpty())
    138. {
    139. std::cerr << "Error: Invalid URL!" << std::endl;
    140. return false;
    141. }
    142. else
    143. return true;
    144. }
    145.  
    146. void NetworkImage::setVerbose(bool x)
    147. {
    148. verbose = x;
    149. }
    150.  
    151. void NetworkImage::setIP(QHostInfo x)
    152. {
    153. if(x.addresses().length() > 0)
    154. {
    155. for(int i=0; i<x.addresses().length();i++)
    156. {
    157. IP.append(x.addresses().at(i).toString());
    158. if(verbose)
    159. {
    160. for(int i=0; i<IP.length();i++)
    161. {
    162. if(verbose)
    163. std::cout << "IP: " << IP.at(i).toStdString() << std::endl;
    164. }
    165. }
    166. }
    167. emit IPRetrieved();
    168. }
    169. }
    170.  
    171. void NetworkImage::askForIP()
    172. {
    173. QHostInfo::lookupHost(url.host(), this, SLOT(setIP(QHostInfo)));
    174. }
    175.  
    176. QStringList NetworkImage::getIPList()
    177. {
    178. return IP;
    179. }
    180.  
    181. void NetworkImage::saveImage(QString & name)
    182. {
    183.  
    184. //QMutexLocker locker(&mutex);
    185. QImage qimageMy;
    186.  
    187. if(qimageMy.loadFromData(byteArray))
    188. {
    189. if(verbose)
    190. {
    191. std::cout << "Downloaded data converted into QImage successfully!" << std::endl;
    192. std::cout << "---------------------------------------------------" << std::endl;
    193. }
    194. IplImage* img = qImage2IplImage(qimageMy);
    195.  
    196. if(!cvSaveImage(name.toStdString().c_str(),img)) printf("Could not save\n");
    197. return;
    198.  
    199. }
    200. else
    201. {
    202. errorOccured = true;
    203. errorString = "Error: Downloaded data does not contain proper image format";
    204. std::cerr << "Error: Downloaded data does not contain proper image format for QImage!" << std::endl;
    205. emit error("Error: Downloaded data does not contain proper image format for QImage!");
    206. return;
    207. }
    208.  
    209. }
    210.  
    211.  
    212. bool NetworkImage::isError()
    213. {
    214. return errorOccured;
    215. }
    216.  
    217.  
    218. QString NetworkImage::getErrorString()
    219. {
    220. return errorString;
    221. }
    222.  
    223. void NetworkImage::printProgress(qint64 bytesRec, qint64 bytesTotal)
    224. {
    225. int oldProgress;
    226. {
    227. QMutexLocker locker(&mutex);
    228. oldProgress = progress;
    229. bytesRecievedPreviously = bytesRecieved;
    230. bytesRecieved = bytesRec;
    231. }
    232. if(bytesTotal>0)
    233. {
    234. std::cout << bytesRec <<std::endl;
    235. std::cout << bytesTotal <<std::endl;
    236. progress = (int)(bytesRec*100/bytesTotal);
    237. if((progress/10 > oldProgress/10))
    238. std::cout<< (int)(bytesRec*100/bytesTotal) << " % " <<std::endl;
    239. }
    240. }
    241.  
    242. void NetworkImage::timerTic()
    243. {
    244. if(!retrieved)
    245. {
    246. QMutexLocker locker(&mutex);
    247. errorOccured = true;
    248. errorString = "Error: Waited to long for any progress";
    249. std::cerr << "Error: Waited to long for any progress!" << std::endl;
    250. emit error("Error: Waited to long for any progress!");
    251. }
    252. }
    To copy to clipboard, switch view to plain text mode 


    Thanks in advance for your help.
    Maciej Napora
    Last edited by Maciej; 29th June 2011 at 14:37.

  2. #2
    Join Date
    Jun 2011
    Location
    Cracow, Poland
    Posts
    2
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QNetworkReply signal downloadProgress returns bytesTotal incorrectly

    It seems that transition from Qt 4.7.0 to 4.7.3 solved the problem for me.

Similar Threads

  1. QtSVG build incorrectly
    By Helios in forum Installation and Deployment
    Replies: 0
    Last Post: 11th July 2010, 05:58
  2. Load image from QNetworkReply incorrectly
    By tqlong in forum Qt Programming
    Replies: 0
    Last Post: 1st July 2010, 16:51
  3. Replies: 1
    Last Post: 23rd January 2010, 22:04
  4. QNetworkReply & delayed readyRead(() signal
    By dmini in forum Qt Programming
    Replies: 1
    Last Post: 6th November 2009, 13:47
  5. Replies: 1
    Last Post: 13th March 2007, 17:33

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.