2012年2月20日月曜日

( Qt C++ )QNetworkAccessManagerを使用する


はいそれでは表題の件やっていきます。
本当はQHttpをやる予定だったのですが、リファレンスを見てもらうとわかるとおり、QHttpではなく、QNetworkAccessManagerの使用を推奨しています。ですのでQHttpをやめて表題の件をやっていきます。
QHttpについてはC++ GUI Programming with Qt4(Nokia無料pdf) 320ページを見るなり、リファレンスを見るなりしてみてください。

QNetworkAccessManagerはざっくりいうとアプリケーションでネットワークへ要求を送信したり、返信を受け取ったりする時に使用するクラスです。

サンプルは独自のものを使用します。

また、いつものようにQtCreaterの使用を前提とします。(QtCreaterなどの使い方は ”Qtをはじめよう" を見てください。)

また.proファイルに QT += network を必ず追加してください。(でなければ動きません。)

ではコードを

(mainwindow.h)
#include <QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QFile>
#include <QMessageBox>
#include <QTextCodec>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
    void replyFinished(QNetworkReply* reply);
private:
    Ui::MainWindow *ui;//uiにはGUI部品に関する記述
    QNetworkAccessManager *manager;
    QFile file;
};

(mainwindow.cpp)
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)//uiにはGUI部品に関する記述
{
    ui->setupUi(this);//uiのGUI部品類初期化

    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());

    manager = new QNetworkAccessManager(this);

    connect(manager, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(replyFinished(QNetworkReply*)));

    file.setFileName("C:\\Users\\windows7\\Desktop\\test.html");
    if (!file.open(QIODevice::WriteOnly))
        return;


    manager->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/doc/qt-4.8/qnetworkaccessmanager.html")));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::replyFinished(QNetworkReply *reply)
{
    QString str;
    if(reply->error() == QNetworkReply::NoError)
    {
        str = tr("ダウンロード正常終了");
        file.write(reply->readAll());
        file.close();
    }
    else
    {
        str = reply->errorString();
        str +=  tr( "    ダウンロード異常終了" );
        file.close();
    }
    QMessageBox msgBox(this);
    msgBox.setText(str);
    msgBox.exec();
}
はい簡単ですね。流れはQtのQNetworkAccessManagerのリファレンスのhtmlを取得しているだけです。
ヘッダ部は説明を省略します。見たままですので。

.cppは説明します。

まずはコンストラクタ。
最初にtrの日本語文字化けを防ぐためコーデックを設定しています。これは各自の環境で違うと思うのでそれぞれの環境にあった設定を設定してください。
次にQNetworkAccessManager managerの終了を監視するためfinished(QNetworkReply*)を自前のreplyFinished(QNetworkReply*)にconnectで接続します。
次にファイルをオープンし、managerのgetで取得を開始します。

デストラクタはそのままなので説明省略します。

replyFinishedはfinished(QNetworkReply*)シグナルへと対応させましたので終了時にこの関数が呼ばれます。
引数のQNetworkReplyには、QNetworkAccessManagerに送信されるデータとヘッダーが含まれています。
この中にエラー情報も含まれているのでまずエラーの有無を確認します。エラーならfileをcloseして終了。エラー無しならreadAllでデータのQByteArrayを取り出しそれをfileに書き込みます。
最後に成功か失敗かをメッセージボックスで表示して終了です。


実行すると以下のようになります。


以上です。