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();

}

运行结果:

 

posted @ 2024-09-25 17:45  [BORUTO]  阅读(86)  评论(0编辑  收藏  举报