Qt - https请求下载图片文件
1、获取一张图片
方法一
在Qt中,你可以使用QNetworkAccessManager
来从网站上获取图片。以下是一个简单的例子,展示了如何使用Qt下载图片:
main.cpp
#include <QApplication>
#include <QSslSocket>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QFile>
#include <QObject>
class ImageDownloader : public QObject
{
Q_OBJECT
public:
ImageDownloader(const QUrl& imageUrl, const QString& savePath): m_imageUrl(imageUrl), m_savePath(savePath)
{
m_manager = new QNetworkAccessManager();
connect(m_manager, &QNetworkAccessManager::finished, this, &ImageDownloader::onDownloadFinished);
QNetworkRequest request(m_imageUrl);
m_manager->get(request);
}
private slots:
void onDownloadFinished(QNetworkReply* reply)
{
if (reply->error())// 处理错误
{
qDebug() << "Download error:" << reply->errorString();
return;
}
QFile file(m_savePath);
if (!file.open(QIODevice::WriteOnly))
{
qDebug() << "Cannot open file for writing";
return;
}
file.write(reply->readAll());
file.close();
qDebug() << "Image saved to" << m_savePath;
}
private:
QNetworkAccessManager* m_manager;
QUrl m_imageUrl;
QString m_savePath;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<< QSslSocket::sslLibraryBuildVersionString();
QUrl imageUrl("https://www.leawo.org/images/7days_prom_en.jpg"); // 替换为实际的图片URL
QString savePath = "./downloaded_image.jpg"; // 图片将被保存到的路径
ImageDownloader downloader(imageUrl, savePath);
return a.exec();
}
确保你的项目文件.pro
包含了网络模块:
QT += network
在这个例子中,ImageDownloader
类负责处理图片下载。它使用QNetworkAccessManager
发送一个GET请求到指定的URL,并在下载完成时将图片保存到本地文件。你需要提供一个有效的图片URL和想要保存图片的文件名。
运行效果:
方法二
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void saveImage(const QString url);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
QString strUrl = QString("https://www.leawo.org/images/7days_prom_en.jpg");
saveImage(strUrl);
}
Widget::~Widget()
{
delete ui;
}
void Widget::saveImage(const QString url)
{
QNetworkRequest request(url);
QNetworkAccessManager *networkManager = new QNetworkAccessManager();
QNetworkReply *reply = networkManager->get(request);
QEventLoop eventLoop;
QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec();
if(reply->error() == QNetworkReply::NoError)
{
QByteArray data = reply->readAll();
QImage image = QImage::fromData(data);
image.save("./test1.png");//说明:这里是通过QImage保存图片数据,也可通过QFile来实现。
}
else
{
qDebug() << reply->errorString();
}
}
运行结果:
方法三
通过sender方法获取QNetworkReply
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void handleNetworkResponse();
private:
Ui::Widget *ui;
// 创建网络访问管理器
QNetworkAccessManager m_manger;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
// 创建请求对象
QNetworkRequest request;
QUrl url("https://www.leawo.org/images/7days_prom_en.jpg");
request.setUrl(url);
// 发出GET请求
QNetworkReply* reply = m_manger.get(request);
// 连接请求完成的信号
QObject::connect(reply, &QNetworkReply::finished, this, &Widget::handleNetworkResponse);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handleNetworkResponse()
{
QObject *obj = QObject::sender(); //sender方法获取QNetworkReply
// 进行其他的槽函数处理操作。
//写法1:
QNetworkReply *reply = qobject_cast<QNetworkReply*>(obj);
//写法2:
//QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
if (obj == nullptr)
{
// sender() 函数在槽函数之外调用是无效的,
// 因此在这里执行错误处理操作。
return;
}
if(reply->error() == QNetworkReply::NoError)
{
QByteArray data = reply->readAll();
QImage image = QImage::fromData(data);
image.save("./test1.png");//说明:这里是通过QImage保存图片数据,也可通过QFile来实现。
}
else
{
qDebug() << reply->errorString();
}
}
2、获取多张图片
方法一
此方法存在一个bug,就是有的时候下载一张图片,会下载不到所有图片。2024/9/27 :已修复此bug
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void handleNetworkResponse();
private:
Ui::Widget *ui;
QList<QUrl> urlList;
//QList<QImage> imageList;
QImage image;
QList<QString> strList;
QList<QNetworkReply*> replyList;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QTimer>
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
// 图片URL列表
QStringList urlStrList;
urlStrList << "https://www.leawo.org/images/7days_prom_en.jpg"
<< "https://www.leawo.org/images/renew_prom_en.jpg"
<< "https://www.leawo.org/jp/images/renew_prom_jp.jpg"
<< "https://www.leawo.org/de/images/renew_prom_de.jpg";
for(int i = 0; i < urlStrList.length(); i++)
{
const QString urlString = urlStrList.at(i);
QUrl url(urlString);//QString转QUrl
urlList.append(url);
}
// 下载图片
for(int i = 0; i < urlList.length(); i++)
{
QNetworkRequest request(urlList.at(i));
QNetworkAccessManager *manager = new QNetworkAccessManager();
//qDebug() << "url = " <<urlList.at(i) << "i = " <<i;
QNetworkReply* reply = manager->get(request);
replyList.append(reply);
// 连接信号槽,处理下载完成
QObject::connect(replyList[i], &QNetworkReply::finished, this, &Widget::handleNetworkResponse);
}
//准备好存图片名字的list
for (int i = 0; i<urlList.length(); i++)
{
QString urlPath = urlList[i].path();
//qDebug() << "urlPath=" << urlPath;
QStringList list = urlPath.split("/"); // 使用"/"作为分隔符
QString filename = list.last(); //获取最后一个字符串
//qDebug() << "filename=" << filename;
strList.append(filename);
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::handleNetworkResponse()
{
QNetworkReply *reply = static_cast<QNetworkReply*>(sender());
static int i = 0;
if (reply->error() == QNetworkReply::NoError)
{
QByteArray data = reply->readAll();
QImage image(QImage::fromData(data));
//qDebug() <<"-----Image downloaded successfully-----";
//qDebug() <<"data = "<<data;
// 处理响应数据
//QString filename = QString("./test%1.png").arg(i);
qDebug() <<"strList[i] = "<<strList[i];
image.save(strList[i]);//说明:这里是通过QImage保存图片数据,也可通过QFile来实现。
i++;
}
else
{
// 处理错误
qDebug() <<"=====Image downloaded error====";
}
// 最后释放 QNetworkReply 对象
reply->deleteLater();
}
运行结果:
方法二
在Qt中,你可以使用QNetworkAccessManager
来从指定的网站上获取多张图片。以下是一个简单的例子,展示了如何使用Qt的网络模块来下载多张图片:
main.cpp
#include <QCoreApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
#include <QObject>
#include <QDebug>
#include <QFile>
QNetworkAccessManager* manager = new QNetworkAccessManager();
void downloadImage(const QUrl& url)
{
QNetworkRequest request(url);
QNetworkReply* reply = manager->get(request);
QObject::connect(reply, &QNetworkReply::finished, [reply, url]()
{
if (reply->error() == QNetworkReply::NoError)
{
QString urlPath = url.path();
qDebug() << "urlPath=" << urlPath;
QStringList list = urlPath.split("/"); // 使用"/"作为分隔符
QString filename = list.last(); //获取最后一个字符串
qDebug() << "filename=" << filename;
// 保存图片到文件
QFile file(filename);
if (!file.open(QIODevice::WriteOnly))
{
qDebug() << "Cannot open file for writing";
return;
}
bool success = file.write(reply->readAll());
if (success)
{
qDebug() << "Image saved successfully";
}
else
{
qDebug() << "Failed to save image";
}
file.close();
}
else
{
qDebug() << "Error downloading image:" << reply->errorString();
}
reply->deleteLater();
});
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QStringList urlStrList;
urlStrList << "https://www.leawo.org/images/7days_prom_en.jpg" << "https://www.leawo.org/images/renew_prom_en.jpg" << "https://www.leawo.org/jp/images/renew_prom_jp.jpg";
QStringList urls = {
"http://example.com/image1.jpg",
"http://example.com/image2.jpg",
"http://example.com/image3.jpg"
// ... 更多图片URL
};
for (const QString& urlString : urlStrList)
{
QUrl url(urlString);
downloadImage(url);
}
return a.exec();
}
确保你的Qt应用程序有足够的权限去写文件到你指定的目录。另外,记得处理网络请求的异常,比如超时、网络断开等问题。这个例子中的下载是同步进行的,实际应用中可能需要考虑使用异步方式来避免界面冻结。
运行结果:
方法三
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QFile>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void downloadImage(QUrl url,int i);
public slots:
//void handleNetworkResponse();
private:
Ui::Widget *ui;
QList<QUrl> urlList;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{
ui->setupUi(this);
QStringList urlStrList;
urlStrList << "https://www.leawo.org/images/7days_prom_en.jpg"
<< "https://www.leawo.org/images/renew_prom_en.jpg"
<< "https://www.leawo.org/jp/images/renew_prom_jp.jpg"
<< "https://www.leawo.org/de/images/7days_prom_de.jpg"
<< "https://www.leawo.org/jp/images/7days_prom_jp.jpg";
for (int i = 0; i<urlStrList.length(); i++)
{
QString urlString = urlStrList.at(i);
QUrl url(urlString);
downloadImage(url,i);
}
}
Widget::~Widget()
{
delete ui;
}
void Widget::downloadImage(QUrl url, int i)
{
urlList.append(url);
//构造请求
QNetworkRequest request(url);
QNetworkAccessManager* manager = new QNetworkAccessManager();
//发送请求
QNetworkReply* reply = manager->get(request);
//开启一个局部的事件循环,等待响应结束,退出
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
//开启子事件循环
loop.exec();
if (reply->error() == QNetworkReply::NoError)
{
QString urlPath = urlList[i].path();
qDebug() << "urlPath=" << urlPath;
QStringList list = urlPath.split("/"); // 使用"/"作为分隔符
QString filename = list.last(); //获取最后一个字符串
qDebug() << "filename=" << filename;
// 保存图片到文件
QFile file(filename);
if (!file.open(QIODevice::WriteOnly))
{
qDebug() << "Cannot open file for writing";
return;
}
bool success = file.write(reply->readAll());
if (success)
{
qDebug() << "========Image saved successfully========";
}
else
{
qDebug() << "Failed to save image";
}
file.close();
}
reply->deleteLater();
}
运行结果: