Qt網路(四)FTP(二)

來源:互聯網
上載者:User

本文章原創於 www.yafeilinux.com 轉載請註明出處。

前面講述了一個最簡單的FTP用戶端程式的編寫,這一節我們將這個程式進行擴充,使其可以瀏覽並能下載伺服器上的所有檔案。

1.更改widget.ui檔案如下。

   

我們刪除了Text Browser ,加入了幾個Label ,Line Edit ,Push Button組件,一個Tree Widget及一個Progress Bar組件。然後我們對其中幾個組件做如下更改。

(1)將“FTP伺服器”標籤後的Line Edit的objectName屬性改為“ftpServerLineEdit”,其text 屬性改為“ftp.qt.nokia.com”。

(2)將“使用者名稱”標籤後的Line Edit的objectName屬性改為“userNameLineEdit”,其text屬性改為“anonymous”,將其toolTip屬性改為“預設使用者名請使用:anonymous ,此時密碼任意。”

(3)將“密碼”標籤後的Line Edit的objectName屬性改為“passWordLineEdit”,其text屬性改為“123456”,將其echoMode屬性改為“Password”。

(4)將“串連”按鈕的objectName屬性改為“connectButton”。

(5)將“返回上一級目錄”按鈕的objectName屬性改為“cdToParentButton”。

(6)將“下載”按鈕的objectName屬性改為“downloadButton”。

(7)將Tree Widget的objectName屬性改為“fileList”,然後在Tree Widget組件上單擊滑鼠右鍵,選擇Edit Items菜單,添加列屬性如下。

 

最終的介面如下。

 

下面我們的程式中,就是實現在使用者填寫完相關資訊後,按下“串連”按鈕,就可以串連到FTP伺服器,並在Tree Widget中顯示伺服器上的所有檔案,我們可以按下“下載”按鈕來下載選中的檔案,並使用進度條顯示下載進度。

2.更改widget.h檔案。

(1)添加標頭檔#include <QtGui>

(2)在private中添加變數:

QHash<QString, bool> isDirectory;

//用來儲存一個路徑是否為目錄的資訊

QString currentPath;

//用來儲存現在的路徑

(3)添加槽函數:

private slots:

    void on_downloadButton_clicked();

    void on_cdToParentButton_clicked();

    void on_connectButton_clicked();

    void ftpCommandFinished(int,bool);

    void ftpCommandStarted(int);

    void updateDataTransferProgress(qint64,qint64 );

    //更新進度條

    void addToList(const QUrlInfo &urlInfo);

    //將伺服器上的檔案添加到Tree Widget中

    void processItem(QTreeWidgetItem*,int);

//雙擊一個目錄時顯示其內容

3.更改widget.cpp的內容。

(1)實現“串連”按鈕的單擊事件槽函數。

void Widget::on_connectButton_clicked()   //連線按鍵

{

    ui->fileList->clear();

    currentPath.clear();

    isDirectory.clear();

    ftp = new QFtp(this);

    connect(ftp,SIGNAL(commandStarted(int)),this,SLOT(ftpCommandStarted(int)));

    connect(ftp,SIGNAL(commandFinished(int,bool)),

this,SLOT(ftpCommandFinished(int,bool)));

    connect(ftp,SIGNAL(listInfo(QUrlInfo)),this,SLOT(addToList(QUrlInfo)));

    connect(ftp,SIGNAL(dataTransferProgress(qint64,qint64)),

            this,SLOT(updateDataTransferProgress(qint64,qint64)));

    QString ftpServer = ui->ftpServerLineEdit->text();

    QString userName = ui->userNameLineEdit->text();

    QString passWord = ui->passWordLineEdit->text();

    ftp->connectToHost(ftpServer,21); //串連到伺服器,預設連接埠號碼是21

    ftp->login(userName,passWord);   //登入

}

我們在“串連”按鈕的單擊事件槽函數中建立了ftp對象,然後關聯了相關的訊號和槽。這裡的listInfo()訊號由ftp->list()函數發射,它將在登入命令完成時調用,下面我們提到。而dataTransferProgress()訊號在資料轉送時自動發射。最後我們從介面上獲得伺服器位址,使用者名稱和密碼等資訊,並以它們為參數執行串連和登入命令。

(2)更改ftpCommandFinished()函數。

我們在相應位置做更改。

首先,在登入命令完成時,我們調用list()函數:

ui->label->setText(tr(“登入成功”));

ftp->list();   //發射listInfo()訊號,顯示檔案清單

然後,在下載命令完成時,我們使下載按鈕可用:

ui->label->setText(tr(“已經完成下載”));

ui->downloadButton->setEnabled(true);

最後再添加一個if語句,處理list命令完成時的情況:

if (ftp->currentCommand() == QFtp::List){

        if (isDirectory.isEmpty())

        { //如果目錄為空白,顯示“empty”

            ui->fileList->addTopLevelItem(

                new QTreeWidgetItem(QStringList()<< tr(“<empty>”)));

            ui->fileList->setEnabled(false);

            ui->label->setText(tr(“該目錄為空白”));

        }

}

我們在list命令完成時,判斷檔案清單是否為空白,如果為空白,就讓Tree Widget不可用,並顯示“empty”條目。

(3)添加檔案清單函數的內容如下。

void Widget::addToList(const QUrlInfo &urlInfo)  //添加檔案清單

{

     QTreeWidgetItem *item = new QTreeWidgetItem;

     item->setText(0, urlInfo.name());

     item->setText(1, QString::number(urlInfo.size()));

     item->setText(2, urlInfo.owner());

     item->setText(3, urlInfo.group());

     item->setText(4, urlInfo.lastModified().toString(“MMM dd yyyy”));

     QPixmap pixmap(urlInfo.isDir() ? “../dir.png” : “../file.png”);

     item->setIcon(0, pixmap);

     isDirectory[urlInfo.name()] = urlInfo.isDir();

     //儲存該路徑是否為目錄的資訊

     ui->fileList->addTopLevelItem(item);

     if (!ui->fileList->currentItem()) {

         ui->fileList->setCurrentItem(ui->fileList->topLevelItem(0));

         ui->fileList->setEnabled(true);

     }

}

當ftp->list()函數執行時會發射listInfo()訊號,此時就會執行addToList()函數,在這裡我們將檔案資訊顯示在Tree Widget上,並在isDirectory中儲存該檔案的路徑及其是否為目錄的資訊。為了使檔案與目錄進行區分,我們使用了不同的表徵圖file.png 和dir.png來表示它們,這兩個表徵圖放在了工程檔案夾中。

(4)將建構函式的內容更改如下。

{

    ui->setupUi(this);

    ui->progressBar->setValue(0);

    connect(ui->fileList,SIGNAL(itemActivated(QTreeWidgetItem*,int)),

            this,SLOT(processItem(QTreeWidgetItem*,int)));

    //滑鼠雙擊列表中的目錄時,我們進入該目錄

}

這裡我們只是讓進度條的值為0,然後關聯了Tree Widget的一個訊號itemActivated()。當滑鼠雙擊一個條目時,發射該訊號,我們在槽函數中判斷該條目是否為目錄,如果是則進入該目錄。

(5)processItem()函數的實現如下。

void Widget::processItem(QTreeWidgetItem* item,int)  //開啟一個目錄

{

    QString name = item->text(0);

    if (isDirectory.value(name)) {  //如果這個檔案是個目錄,則開啟

        ui->fileList->clear();

        isDirectory.clear();

        currentPath += ‘/’;

        currentPath += name;

        ftp->cd(name);

        ftp->list();

        ui->cdToParentButton->setEnabled(true);

    }

}

(6)“返回上一級目錄”按鈕的單擊事件槽函數如下。

void Widget::on_cdToParentButton_clicked()  //返回上級目錄按鈕

{

    ui->fileList->clear();

    isDirectory.clear();

    currentPath = currentPath.left(currentPath.lastIndexOf(‘/’));

    if (currentPath.isEmpty()) {

        ui->cdToParentButton->setEnabled(false);

        ftp->cd(“/”);

    } else {

        ftp->cd(currentPath);

    }

    ftp->list();

}

在返回上一級目錄時,我們取當前路徑的最後一個“/”之前的部分,如果此時路徑為空白了,我們就讓“返回上一級目錄”按鈕不可用。

(7)“下載”按鈕單擊事件槽函數如下。

void Widget::on_downloadButton_clicked()  //下載按鈕

{

    QString fileName = ui->fileList->currentItem()->text(0);

    QFile *file = new QFile(fileName);

    if (!file->open(QIODevice::WriteOnly))

    {

        delete file;

        return;

    }

    ui->downloadButton->setEnabled(false); //下載按鈕不可用,等下載完成後才可用

    ftp->get(ui->fileList->currentItem()->text(0), file);

}

在這裡我們擷取了當前項目的檔案名稱,然後建立檔案,使用get()命令下載伺服器上的檔案到我們建立的檔案中。

(8)更新進度條函數內容如下。

void Widget::updateDataTransferProgress( //進度條

        qint64 readBytes,qint64 totalBytes)

{

    ui->progressBar->setMaximum(totalBytes);

    ui->progressBar->setValue(readBytes);

}

 

 

 

 

 

4.運行程式,效果如下。

開始介面如下。

 

登入成功時介面如下。

 

下載檔案時介面如下。

 

當一個目錄為空白時介面如下。

 

4.流程說明。

整個程式的流程就和我們實現函數的順序一樣。使用者在介面上輸入伺服器的相關資訊 ,然後我們利用這些資訊進行串連並登入伺服器,等登入伺服器成功時,我們列出伺服器上所有的檔案。對於一個目錄,我們可以進入其中,並返回上一級目錄,我們可以下載檔案,並顯示下載的進度。

    對於ftp的操作,全部由那些命令和訊號來完成,我們只需要調用相應的命令,並在其發出訊號時,進行對應的處理就可以了。而對於檔案的顯示,則是視圖部分的知識了。

5.其他說明。

最後需要說明的是,因為為了更好的講解知識,使得程式簡單化,所以我們省去了很多細節上的處理,如果需要,你可以自己添加。比如中斷連線和取消下載,你都可以使用

ftp->abort()函數。你也可以參考Qt內建的Ftp Example例子。對於其他動作,比如上傳等,你可以根據需要添加。

      FTP的相關編程就講到到這裡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.