2

これは純粋なテスト目的であり、私の好奇心のためです。DataDownloader クラスを使用して、サーバーからデータのリストを取得します。http://tiny-file-urlhttp://big-file-urlなど、さまざまな URL で動作します。しかし、http://tiny-file-url と http://tiny-file-url という 2 つの同一の URL を渡し、http: //tiny-file-urlからデータが非常に小さい場合、2 番目の応答はfrom QNetworkAccessManager は空です。ただし、2 つのhttp://big-file-urlは機能しているようです。同じ URL から小さなデータを要求するときに、QNetworkAccessManager が何らかの魔法をかけるかどうか疑問に思っていますか? Qtドキュメントサイトで関連情報を取得できないようです。

これが私のDataDownloaderクラスです:

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

これを呼び出すコードDataDownloaderは次のとおりです。

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);
    }
}
4

1 に答える 1

1

ここは、スロットisCompleteに接続する前に放出されると思います。downloadPlugins最初にこの信号を接続してから、ダウンロード アクションを実行してみてください。

m_pPluginDownloader = new DataDownloader(url);

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

m_pPluginDownloader.download();

コンストラクターで get アクションを実行する代わりに、 というスロットで実行しますdownload

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

DataDownloaderもう 1 つのポイントは、毎回新しいインスタンスを作成する必要がないことです。コンストラクターでインスタンスを作成し、そこに信号PluginManagerを接続できます。isCompleteその後、URL をdownloadスロットの引数として指定できます。

于 2015-02-06T18:58:54.573 に答える