J'ai ce code:

QNetworkAccessManager man;
QNetworkRequest req(QUrl("URL"));
QString ua("HttpRequestDemo/0.1 (Win64) Qt/5.14.0");
req.setHeader(QNetworkRequest::UserAgentHeader, QVariant(ua));
QNetworkReply* reply = man.get(req);
QObject::connect(reply){
    QByteArray read = reply->readLine();
    QFile out("file.txt");
    out.open(QIODevice::WriteOnly|QIODevice::Text);
    out.write(read);
    out.close();
})

Cela fonctionne sur le fichier main.cpp, en utilisant QCoreApplication, mais je souhaite utiliser QApplication et télécharger des données spécifiques tout en appuyant sur un bouton.

J'ai mis le même code sur on_pushButton_clicked () dans le fichier mainwindow.cpp et il n'a même pas généré le fichier à partir de l'url.

0
Branda 2 avril 2020 à 20:18

3 réponses

Meilleure réponse

Le problème est que man et req sortent de la portée et sont détruits dès que votre fonction on_pushButton_clicked() est renvoyée, auquel cas la requête n'a probablement même pas encore été envoyée.

Vous devez vous assurer que ces objets survivent à la portée actuelle, soit en les rendant membres de la classe window, soit en les allouant sur le tas et en définissant certains QObject (peut-être aussi la classe window) comme parent.

0
Thomas 2 avril 2020 à 17:30

Le problème est que si vous mettez le même code dans une méthode comme X, vous faites de QNetworkAccessManager une variable locale qui sera supprimée instantanément que la connexion est asynchrone. La solution est de faire de QNetworkAccessManager un attribut de la classe.

* .h

private:
    QNetworkAccessManager man;

* .cpp

void Klass::on_pushButton_clicked(){
    QNetworkRequest req(QUrl("URL"));
    QString ua("HttpRequestDemo/0.1 (Win64) Qt/5.14.2");
    req.setHeader(QNetworkRequest::UserAgentHeader, QVariant(ua));
    QNetworkReply* reply = man.get(req);
    connect(reply, &QNetworkReply::finished, [&]() {
        QByteArray read = reply->readAll();
        QFile out("file.txt");
        out.open(QIODevice::WriteOnly|QIODevice::Text);
        out.write(read);
        out.close();
        reply->close();
        reply->deleteLater();
    })
}
0
eyllanesc 2 avril 2020 à 17:31

Si vous prévoyez de mettre en file d'attente de très nombreux téléchargements, je vous recommande fortement d'utiliser libcurl dans votre application Qt. J'utilisais QNetworkAccessManager pour télécharger plus de 100 fichiers de devis financiers, et le téléchargement échouait ~ 1/3 du temps, et le téléchargement prendrait un certain temps. Je suis passé à libcurl, et après avoir compris comment configurer mes certificats racine crypto pour https, il fonctionne beaucoup plus rapidement et n'échoue presque jamais. Je l'exécute en tant que dll.

Et oui, vous devrez vous assurer que le gestionnaire de réseau, qu'il s'agisse de QNetworkManager ou de curl, ne sort pas du champ d'application en quittant le gestionnaire de boutons. Un modèle plus conventionnel, bien que pas nécessairement meilleur, consiste soit à avoir un pointeur vers par ex. QNetworkManager dans votre classe parent, et le nouveau, ou utilisez un std :: unique_ptr et std :: make_unique (prétendument plus sûr). La création d'objets volumineux sur la pile peut causer des problèmes (dans l'ancien temps, j'ose dire, des débordements de pile), et cela se fait généralement sur le tas. Dans ce cas, ce n'est pas très gros, donc ça n'a pas vraiment d'importance. Alternativement, un formulaire créant de gros objets peut lui-même être créé sur le tas.

0
CodeLurker 2 avril 2020 à 17:48