Jerry
Jerry

Reputation: 1812

Qt QNetworkReply readAll returns empty when request the same url again

This is for pure testing purpose and for my curiosity. I use my DataDownloader class to get a list of data from server. It works with different urls, like http://tiny-file-url, http://big-file-url. But if I pass in two identical urls, http://tiny-file-url, http://tiny-file-url, and the data from http://tiny-file-url is quite small, then the second reply from QNetworkAccessManager is empty. However two http://big-file-url seem to work. I'm wondering if QNetworkAccessManager does some magic when request small data from the same url? I can't seem to get any relevant information on Qt document site.

Here is my DataDownloader class:

class DataDownloader : public QObject
{
    Q_OBJECT

public:
    explicit DataDownloader(QObject* parent = 0);
    virtual ~DataDownloader();

    QByteArray data() const;
    void cancel();
    void download(QUrl url);

    signals:
    void isComplete();

    private slots:
    void complete(QNetworkReply* reply);

    private:
    QNetworkAccessManager m_NetworkManager;
    QByteArray m_Data;
    QNetworkReply* m_pReply;
};

DataDownloader::DataDownloader(QUrl url, QObject* parent) :QObject(parent)
{
    connect(&m_NetworkManager, SIGNAL(finished(QNetworkReply*)),
            SLOT(complete(QNetworkReply*)));
}

DataDownloader::~DataDownloader()
{
}

void DataDownloader::complete(QNetworkReply* reply)
{
    // in the first download it returns data
    // but the second time m_Data is empty
    m_Data = reply->readAll();
    reply->deleteLater();

    if (!m_Data.isEmpty()) {
        // no signal on the second try
        emit isComplete();
    }
}

QByteArray DataDownloader::data() const
{
    return m_Data;
}

void DataDownloader::cancel()
{
    m_pReply->abort();
}

void DataDownloader::download(QUrl url)
{
    QNetworkRequest request(url);
    m_pReply = m_NetworkManager.get(request);
}

The code that invokes this DataDownloader is as below:

void PluginManager::downloadPlugins()
{
    m_DownloadIndex++;

    savePlugin();

    if (m_DownloadIndex < m_PluginList.size()) {
        QUrl url;
        // alway return the same url here
        QString pluginUrl = getPluginUrl(m_PluginList.at(m_DownloadIndex));
        url.setUrl(pluginUrl);

        if (m_pPluginDownloader == NULL) {
            m_pPluginDownloader = new DataDownloader();
            // call this function again when isComplete is signaled
            connect(m_pPluginDownloader, SIGNAL(isComplete()), this, SLOT(downloadPlugins()));
        }
        m_pPluginDownloader->download(url);
    }
}

Upvotes: 2

Views: 1480

Answers (1)

Nejat
Nejat

Reputation: 32635

I think here isComplete is emitted before you connect it to downloadPluginsslot. Try to first connect this signal and then do the download action :

m_pPluginDownloader = new DataDownloader(url);

connect(m_pPluginDownloader, SIGNAL(isComplete()), this, SLOT(downloadPlugins()));

m_pPluginDownloader.download();

Instead of performing get action in the constructor, do it in a slot called download :

void DataDownloader::download()
{
    QNetworkRequest request(url);
    m_pReply = m_NetworkManager.get(request);
}

Another point is that it's not necessary to make a new instance of DataDownloaderevery time. You can create an instance in the constructor of PluginManager and connect isComplete signal once there. You can then provide the url as argument in download slot.

Upvotes: 1

Related Questions