Reputation: 71
I am trying to download and save some images with Qt in a console appplication. Here is what I got so far, (all code is compiling, but after run, it seems to don't enter to replyFinished()
function...)
void Test::start()
{
std::cout << "start1";
QNetworkAccessManager *manager = new QNetworkAccessManager();
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://www.exylum.mydevil.net/firefox.jpg")));
}
void Test::replyFinished(QNetworkReply* reply)
{
std::cout << "st";
QImage* img2 = new QImage();
img2->loadFromData(reply->readAll());
if(img2->isNull())
std::cout << "oops";
if(img2->save("omg2.jpg", "JPG"))
std::cout << "saved";
else
std::cout << "dont...";
}
Upvotes: 6
Views: 14119
Reputation: 99
You can have a look at my project. It searches images on Flickr and displays the images in QListWidget. Features:
Link: https://github.com/hbkvikas/FlickrImageSearch It's working well but improvements can also be suggested. Screenshot for the application
Upvotes: 0
Reputation: 1484
None of above solution didn't work for me. But i found this Qt wiki page that worked perfectly for all type of data.
Upvotes: 3
Reputation: 1243
This Question is old, but I had a similar problem and now I have a solution for Qt 5.8.
The code is designed to work fast and the network requests are done in an asynchronous way. Therefore you have to provide an ID for each call to know which replay has finished.
Additionally, this code uses SSL. If you don't want to use SSL encryption delete the 4 lines with QSslConfiguartion.
filedownloader.h:
#ifndef FILEDOWNLOADER_H
#define FILEDOWNLOADER_H
#include <QObject>
#include <QStringList>
#include <QFile>
#include <QDir>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
class FileDownloader : public QObject
{
Q_OBJECT
public:
explicit FileDownloader(QObject *parent = 0);
virtual ~FileDownloader();
void downloadFile(QUrl url, QString id, QString dir_absolute_path);
signals:
// emits error string
void error(QString);
// Emits path to img on disk and id
void downloaded(QString, QString);
private slots:
void fileDownloaded();
void onReadyRead();
private:
QNetworkAccessManager *webCtrl;
QMap<QNetworkReply*, QFile*> replytofile;
QMap<QNetworkReply*, QPair<QString, QString> > replytopathid;
const QByteArray userAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36";
};
#endif // FILEDOWNLOADER_H
filedownloader.cpp:
#include "filedownloader.h"
#include <QDebug>
FileDownloader::FileDownloader(QObject *parent) :
QObject(parent),
webCtrl(new QNetworkAccessManager(this))
{
}
FileDownloader::~FileDownloader()
{
delete webCtrl;
}
void FileDownloader::downloadFile(QUrl url, QString id, QString dir_absolute_path)
{
QString url_string = url.toString();
QString path = dir_absolute_path + url_string.right(url_string.size() - url_string.lastIndexOf("/"));
QFile *file = new QFile(path, this);
if(!file->open(QIODevice::WriteOnly))
{
return;
}
QNetworkRequest request(url);
request.setRawHeader("User-Agent", userAgent);
QSslConfiguration sslConfiguration(QSslConfiguration::defaultConfiguration());
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
sslConfiguration.setProtocol(QSsl::AnyProtocol);
request.setSslConfiguration(sslConfiguration);
QNetworkReply *reply = webCtrl->get(request);
replytofile.insert(reply, file);
replytopathid.insert(reply, QPair<QString, QString>(path, id));
QObject::connect(reply, &QNetworkReply::finished, this, &FileDownloader::fileDownloaded);
QObject::connect(reply, &QNetworkReply::readyRead, this, &FileDownloader::onReadyRead);
}
void FileDownloader::fileDownloaded()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if (replytofile[reply]->isOpen())
{
replytofile[reply]->close();
replytofile[reply]->deleteLater();
}
switch(reply->error())
{
case QNetworkReply::NoError:
break;
default:
emit error(reply->errorString().toLatin1());
break;
}
emit downloaded(replytopathid[reply].first, replytopathid[reply].second);
replytofile.remove(reply);
replytopathid.remove(reply);
delete reply;
}
void FileDownloader::onReadyRead()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
replytofile[reply]->write(reply->readAll());
}
Upvotes: 0
Reputation: 156
This is an old question, but for reference, I'll post a working version of @lwinhtooko's code:
downloader.h:
#pragma once
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QObject>
#include <QUrl>
class Downloader : public QObject {
Q_OBJECT
QFile *m_file;
bool m_isReady = true;
public:
explicit Downloader(QObject *parent = 0) : QObject(parent) {}
virtual ~Downloader() { delete m_file; }
void downloadFileFromURL(const QString &url, const QString &filePath);
private slots:
void onDownloadFileComplete(QNetworkReply *reply);
};
downloader.cpp:
#include "downloader.h"
void Downloader::downloadFileFromURL(const QString &url, const QString &filePath) {
if (!m_isReady)
return;
m_isReady = false;
const QString fileName = filePath + url.right(url.size() - url.lastIndexOf("/")); // your filePath should end with a forward slash "/"
m_file = new QFile();
m_file->setFileName(fileName);
m_file->open(QIODevice::WriteOnly);
if (!m_file->isOpen()) {
m_isReady = true;
return; // TODO: permission check?
}
QNetworkAccessManager *manager = new QNetworkAccessManager;
QNetworkRequest request;
request.setUrl(QUrl(url));
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(onDownloadFileComplete(QNetworkReply *)));
manager->get(request);
}
void Downloader::onDownloadFileComplete(QNetworkReply *reply) {
if (!m_file->isWritable()) {
m_isReady = true;
return; // TODO: error check
}
m_file->write(reply->readAll());
m_file->close(); // TODO: delete the file from the system later on
m_isReady = true;
}
The issue appeared to be the way QNetworkReply
was being used.
Upvotes: 2
Reputation: 2406
Download Image using QNetworkAccessManager
header file
#ifndef QDOWNLOADER_H
#define QDOWNLOADER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QFile>
#include <QStringList>
class QDownloader : public QObject
{
Q_OBJECT
public:
explicit QDownloader(QObject *parent = 0);
virtual ~QDownloader();
void setFile(QString fileURL);
private:
QNetworkAccessManager *manager;
QNetworkReply *reply;
QFile *file;
private slots:
void onDownloadProgress(qint64,qint64);
void onFinished(QNetworkReply*);
void onReadyRead();
void onReplyFinished();
};
#endif // QDOWNLOADER_H
source file
#include "qdownloader.h"
QDownloader::QDownloader(QObject *parent) :
QObject(parent)
{
manager = new QNetworkAccessManager;
}
QDownloader::~QDownloader()
{
manager->deleteLater();
}
void QDownloader::setFile(QString fileURL)
{
QString filePath = fileURL;
QString saveFilePath;
QStringList filePathList = filePath.split('/');
QString fileName = filePathList.at(filePathList.count() - 1);
saveFilePath = QString("C:/Images/" + fileName );
QNetworkRequest request;
request.setUrl(QUrl(fileURL));
reply = manager->get(request);
file = new QFile;
file->setFileName(saveFilePath);
file->open(QIODevice::WriteOnly);
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(onDownloadProgress(qint64,qint64)));
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(onFinished(QNetworkReply*)));
connect(reply,SIGNAL(readyRead()),this,SLOT(onReadyRead()));
connect(reply,SIGNAL(finished()),this,SLOT(onReplyFinished()));
}
void QDownloader::onDownloadProgress(qint64 bytesRead,qint64 bytesTotal)
{
qDebug(QString::number(bytesRead).toLatin1() +" - "+ QString::number(bytesTotal).toLatin1());
}
void QDownloader::onFinished(QNetworkReply * reply)
{
switch(reply->error())
{
case QNetworkReply::NoError:
{
qDebug("file is downloaded successfully.");
}break;
default:{
qDebug(reply->errorString().toLatin1());
};
}
if(file->isOpen())
{
file->close();
file->deleteLater();
}
}
void QDownloader::onReadyRead()
{
file->write(reply->readAll());
}
void QDownloader::onReplyFinished()
{
if(file->isOpen())
{
file->close();
file->deleteLater();
}
}
Upvotes: 4
Reputation: 2406
header file
#ifndef IMAGEDOWNLOAD_H
#define IMAGEDOWNLOAD_H
#include <QWidget>
#include <QHttp>
#include <QFile>
#include <QUrl>
class ImageDownload : public QWidget
{
Q_OBJECT
public:
explicit ImageDownload(QWidget *parent = 0);
private:
int httpGetId;
QHttp http;
QFile myfile;
private slots:
void httpRequestFinished(int, bool);
void progress(int,int);
};
#endif // IMAGEDOWNLOAD_H
source file
#include "imagedownload.h"
ImageDownload::ImageDownload(QWidget *parent) :
QWidget(parent)
{
QUrl url("url of image.");
myfile.setFileName("C:/Qt/imagefilename");
myfile.open(QIODevice::WriteOnly);
connect(&http,SIGNAL(requestFinished(int,bool)),this,SLOT(httpRequestFinished(int,bool)));
connect(&http,SIGNAL(dataReadProgress(int,int)),this,SLOT(progress(int,int)));
http.setHost(url.host(),QHttp::ConnectionModeHttp,url.port());
httpGetId = http.get(url.path(),&myfile);
}
void ImageDownload::httpRequestFinished(int id, bool error)
{
if(id == httpGetId)
{
myfile.close();
}
if(error)
{
qDebug(http.errorString().toLatin1());
}
}
void ImageDownload::progress(int a, int b)
{
qDebug(QString::number(a).toLatin1()+" : "+QString::number(b).toLatin1());
}
Upvotes: 0