閱讀672 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[Qt教程] 第33篇 網絡(三)FTP(一)

[Qt教程] 第33篇 網絡(三)FTP(一)

樓主
 發表於 2013-9-4 14:52:46 | 查看: 392| 回複: 8
FTP(一)


版權聲明

該文章原創於作者yafeilinux,轉載請注明出處!



導語

上一節我們講述了HTTP的編程,這一節講述與其及其相似的FTP的編程。FTPFileTransfer Protocol,也就是文件傳輸協議。FTP的主要作用,就是讓用戶連接上一個遠程計算機,查看遠程計算機有哪些文件,然後把文件從遠程計算機上拷貝到本地計算機,或者把本地計算機的文件送到遠程計算機上。


環境:Windows Xp + Qt 4.8.5+QtCreator 2.8.0


目錄

一、簡介
二、實現簡單的文件下載


正文


一、簡介

在Qt中,我們可以使用上一節講述的QNetworkAccessManager和QNetworkReply類來進行FTP 程序的編寫,因為它們用起來很簡單。但是,對於較複雜的FTP操作,Qt還提供了QFtp類,利用這個類,我們很容易寫出一個FTP客戶端程序。下麵我們先在幫助中查看這個類。

01.jpg


QFtp中,所有的操作都對應一個特定的函數,我們可以稱它們為命令。如connectToHost()連接到服務器命令,login()登錄命令,get()下載命令,mkdir()新建目錄命令等。因為QFtp類以異步方式工作,所以所有的這些函數都不是阻塞函數。也就是說,如果一個操作不能立即執行,那麼這個函數就會直接返回,直到程序控製權返回Qt事件循環後才真正執行,它們不會影響界麵的顯示。

所有的命令都返回一個int 型的編號,使用這個編號讓我們可以跟蹤這個命令,查看其執行狀態。當每條命令開始執行時,都會發出commandStarted()信號,當該命令執行結束時,會發出commandFinished()信號。我們可以利用這兩個信號和命令的編號來獲取命令的執行狀態。當然,如果不想執行每條命令都要記下它的編號,也可以使用currentCommand()來獲取現在執行的命令,其返回值與命令的對應關係如下圖。

02.jpg


二、實現簡單的文件下載

下麵我們先看一個簡單的FTP客戶端的例子,然後對它進行擴展。在這個例子中我們從FTP服務器上下載一個文件並顯示出來。

1.我們新建Qt Gui應用。
項目名次為“myFtp”,基類選擇QWidget,類名保持Widget即可。完成後打開muFtp.pro文件,在上麵添加一行:QT += network,然後保存該文件。

2.修改widget.ui文件。
在其中添加一個TextBrowser 和一個 Label,效果如下。
03.jpg

3.main.cpp中進行修改。
為了在程序中可以使用中文,我們在main.cpp中添加頭文件#include <QTextCodec>
並在main()函數中添加代碼:
QTextCodec::setCodecForTr(QTextCodec::codecForLocale());


4.widget.h中進行修改。
先添加頭文件:#include <QFtp>
再在private中定義對象:QFtp *ftp;
添加私有槽函數:
private slots:
    void ftpCommandStarted(int);
void ftpCommandFinished(int,bool);

5.widget.cpp中進行更改。
1)在構造函數中添加代碼:
  1. ftp = new QFtp(this);
  2. ftp->connectToHost("ftp.qt-project.org"); //連接到服務器
  3. ftp->login();   //登錄
  4. ftp->cd("qt/source");   //跳轉到“qt”目錄下的source目錄中
  5. ftp->get("INSTALL");  //下載“INSTALL”文件
  6. ftp->close();   //關閉連接

  7. // 當每條命令開始執行時發出相應的信號
  8. connect(ftp,SIGNAL(commandStarted(int)),
  9.         this,SLOT(ftpCommandStarted(int)));

  10. // 當每條命令執行結束時發出相應的信號
  11. connect(ftp,SIGNAL(commandFinished(int,bool)),
  12.         this,SLOT(ftpCommandFinished(int,bool)));
複製代碼
我們在構造函數裏執行了幾個FTP的操作,登錄站點,並下載了一個文件。然後又關聯了兩個信號和槽,用來跟蹤命令的執行情況。


2)實現槽函數:
void Widget::ftpCommandStarted(int)
{
    if(ftp->currentCommand() == QFtp::ConnectToHost){
       ui->label->setText(tr("正在連接到服務器..."));
    }
    if (ftp->currentCommand() == QFtp::Login){
       ui->label->setText(tr("正在登錄..."));
    }
    if (ftp->currentCommand() == QFtp::Get){
       ui->label->setText(tr("正在下載..."));
    }
    else if (ftp->currentCommand() == QFtp::Close){
       ui->label->setText(tr("正在關閉連接..."));
    }
}

每當命令執行時,都會執行ftpCommandStarted()函數,它有一個參數int id,這個id就是調用命令時返回的id,如int loginID= ftp->login(); 這時,我們就可以用if(id == loginID)來判斷執行的是否是login()函數。但是,我們不想為每個命令都設置一個變量來存儲其返回值,所以,我們這裏使用了ftp->currentCommand() ,它也能獲取當前執行的命令的類型。在這個函數裏我們讓開始不同的命令時顯示不同的狀態信息。

void Widget::ftpCommandFinished(int,bool error)
{
    if(ftp->currentCommand() == QFtp::ConnectToHost){
       if(error)
           ui->label->setText(tr("連接服務器出現錯誤:%1")
                               .arg(ftp->errorString()));
       else ui->label->setText(tr("連接到服務器成功"));
    }
    if (ftp->currentCommand() == QFtp::Login){
       if(error)
           ui->label->setText(tr("登錄出現錯誤:%1")
                               .arg(ftp->errorString()));
       else ui->label->setText(tr("登錄成功"));
    }
    if (ftp->currentCommand() == QFtp::Get){
       if(error)
           ui->label->setText(tr("下載出現錯誤:%1")
                               .arg(ftp->errorString()));
       else {
           ui->label->setText(tr("已經完成下載"));
           ui->textBrowser->setText(ftp->readAll());
       }
    }
    else if (ftp->currentCommand() == QFtp::Close){
       ui->label->setText(tr("已經關閉連接"));
    }
}

這個函數與ftpCommandStarted()函數相似,但是,它是在一個命令執行結束時執行的。它有兩個參數,第一個intid,就是調用命令時返回的編號,我們在上麵已經講過了。第二個是bool error,它標誌現在執行的命令是否出現了錯誤。如果出現了錯誤,那麼error true ,否則為false。我們可以利用它來輸出錯誤信息。在這個函數中,我們在完成一條命令時顯示不同的狀態信息,並顯示可能的出錯信息。在if (ftp->currentCommand() == QFtp::Get) 中,也就是已經完成下載時,我們讓textBrowser顯示下載的信息。


6.運行程序,效果如下。

04.jpg


7.出錯演示。
下麵我們演示一下出錯時的情況。
將構造函數中的代碼ftp->login();改為ftp->login("tom","123456");
這時我們再運行程序:
05.jpg

可以看到,它輸出了錯誤信息,指明了錯誤的指令和出錯的內容。其實我們設置的這個錯誤,也是想告訴大家,在FTP中如果沒有設置用戶名和密碼,那麼默認的用戶名應該是anonymous,這時密碼可以任意填寫,而使用其他用戶名是會出錯的。



結語

     在下一節中,我們將會對這個程序進行擴展,讓它可以瀏覽服務器上的所有文件,並進行下載。




涉及的源碼下載:  myFtp1.rar (2.09 KB, 下載次數: 1) 


最後更新:2017-04-03 14:54:15

  上一篇:go Java IO--數據操作流DataOutputStream/DataInputStream
  下一篇:go [Qt教程] 第14篇 2D繪圖(四)繪製路徑