QT HTTP接收多个数据包生成图片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/theArcticOcean/article/details/78943288

看了看电脑右上角的时间,2017就要彻底流逝了。再瞅了瞅本月的文章数,天啦,只有一篇,近一个月没有时间学习,没有时间写文章,没有时间休息,总之就是没时间……好强烈的罪恶感,赶紧抓住最后的几个小时,补上一文!
我们知道简单的HTTP请求可以一次返回结果,但对于一些数据量较大的情况,则要分多次返回。
QNetworkAccessManager下的QNetworkReply有readyRead信号,一旦该信号产生,就可以读取相应的数据并写入文件中。
对于较大的文件,比如图片,一个http请求需要分多个数据包返回结果最后才能得到完整的集合。
好在有QNetworkReply::finished。该信号提示我们不会再有数据更新了,此时就可以关闭文件流,结束数据存储。

如下:

    request = new QNetworkRequest ();

    manager = new QNetworkAccessManager(this);

    request->setUrl(QUrl("https://static.baydn.com/static/img/icon_head.png"));

    reply = manager->get(*request);

    connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));

    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),

          this, SLOT(slotError(QNetworkReply::NetworkError)));

    // SSL(Secure Sockets Layer 安全套接层), it encrypts data.

    connect(reply, SIGNAL(sslErrors(QList<QSslError>)),

            this, SLOT(slotSslErrors(QList<QSslError>)));

    connect(reply, SIGNAL(finished()), this, SLOT(slotFinished()));

数据存储函数:

void HttpManager::slotReadyRead()
{
    static int time = 0;
    QByteArray bytes = reply->readAll();
    QString url = reply->request().url().toString();
    int fd;
    if(searchFilesMap(url.toStdString())){  //if fd exist, we append data to local file.
        fd = filesMap[url.toStdString()];
        size_t ret = write(fd, bytes.toStdString().c_str(), bytes.size());
        if(ret <= 0){
            LOGDBG("write failed: %s", strerror(errno));
        }
    }
    else {  //if not exist, we. open and write.
        string path = getIncomLocalPicPath(url.toStdString());
        fd = open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC);
        if(fd == -1){
            LOGDBG("open failed, %s",strerror(errno));
            return ;
        }
        fchmod(fd, 0777);
        size_t ret = write(fd, bytes.toStdString().c_str(), bytes.size());
        if(ret <= 0){
            LOGDBG("write failed: %s", strerror(errno));
        }
        // add info to map
        filesMap[url.toStdString()] = fd;
    }

    LOGDBG("%d finished, fd: %d, url: %s",++time, fd, reply->request().url().toString().toStdString().c_str());
}

结束函数:
关闭句柄并重命名。

void HttpManager::slotFinished()
{
    QString url = reply->request().url().toString();
    QByteArray bytes = reply->readAll();
    int fd = filesMap[url.toStdString()];
    close(fd);
    string f1;
    string f2;
    f1 = getIncomLocalPicPath(url.toStdString());
    f2 = getComLocalPicPath(url.toStdString());
    if(0 != rename(f1.c_str(),f2.c_str())){
        LOGDBG("rename failed: %s", strerror(errno));
    }
    LOGDBG("%d, finished.", fd);
}

执行:

$ ./http_test 
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead]  1 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead]  2 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead]  3 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead]  4 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 152, funcName: slotReadyRead]  5 finished, fd: 19, url: https://static.baydn.com/static/img/icon_head.png
[file: httpmanager.cpp, line: 181, funcName: slotFinished]  19, finished.

阅读更多

没有更多推荐了,返回首页