A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

首先明确一点:实现ftp断点续传,需要服务器支持,我使用的是CentOS 下的vsftpd作为ftp服务器。

  FTP连接一般是有两个连接,一种连接时客户端C与服务器端S传送命令,一种连接是用于数据的传输。而FTP连接支持两种模式

  Port模式(主动模式):涉及到的端口号有21和20,当客户端C向服务器端S通过端口21发送请求链接时,服务器端接收连接,并打开一条命令链路。当客户端需要传输数据时,便会通过命令链路向服务器端发送PORT命令请求:我打开了xxx端口,你连接我吧。服务器端接受请求,通过端口号为21向客户端xxx端口建立一条数据传输链路发送数据。

  passiv模式(被动模式):客户端C向服务器端(端口21)发送请求连接,服务器端接收并打开一条命令链路。当客户端需要传输数据时,会通过命令链路像服务器端发送passiv命令:我打开了XXX端口,你连接我吧,服务器端接受请求,从端口1024-5000中随机选择一个端口与客户端建立链接,并发送命令:我打开了XXX端口,你过来链接吧,客户端接受后就向该端口发送数据。

由此可知,port模式是客户端打开一个本地端口,等待服务器端进行数据连接,而passiv模式是由服务器打开一个端口,等待客户端进行数据连接。

QFtp具有文件上传以及下载功能,

但是对于文件的续传支持上不好,因此 我使用Qt5.2.1编译器,从网络上下载了QFtp的实现,对其进行修改。目前为止,可以实现文件的续传功能。

QFtp默认采用(PASV)被动模式进行文件传输

QFtp续传:http://download.csdn.net/detail/jiezhj/7528025

以下是我封装的ftpManager

//头文件



  • #ifndef FTPMANAGER_H



  • #define FTPMANAGER_H







  • #include <QObject>



  • #include <QDebug>



  • #include <QThread>



  • #include <QFile>



  • #include <QTcpSocket>



  • #include "qftp.h"







  • class FtpManager : public QObject



  • {



  •     Q_OBJECT



  • public:



  •     explicit FtpManager(QString _host, QString userName = "", QString passWd = "",qint16 _port = 21,QObject *parent = 0);



  •     ~FtpManager();







  • signals:



  •     void G_getProgressVal(int);







  • public slots:



  •     void S_commandFinish(int,bool);



  •     void S_upDateProgress(qint64,qint64);







  •     void S_abort();



  •     void S_dloadFile(QString _remoteFile,QString _localFile,bool isRese = false);



  •     void S_uloadFile(QString _localFile,QString _remoteFile,bool isRese = false);















  • private:







  •     QString         m_userName;



  •     QString         m_passwd;







  •     QFtp            *myFtp;



  •     QFile           *m_File;



  •     bool            m_IsOpenFile;







  • };











  • #endif // FTPMANAGER_H


//实现



  • #include "ftpmanager.h"







  • class FtpManager;







  • FtpManager::FtpManager(QString _host, QString userName, QString passWd, qint16 _port, QObject *parent):



  •     QObject(parent),



  •     m_userName(userName),



  •     m_passwd(passWd),



  •     m_File(0),



  •     m_IsOpenFile(false)



  • {



  •     //构建ftp对象



  •     myFtp = new QFtp(this);



  •     //连接ftp服务器



  •     myFtp->connectToHost(_host,_port);



  •     //进度条显示



  •     connect(myFtp,SIGNAL(dataTransferProgress(qint64,qint64)),



  •             SLOT(S_upDateProgress(qint64,qint64)));



  •     //状态显示



  •     connect(myFtp,SIGNAL(commandFinished(int,bool)),



  •             SLOT(S_commandFinish(int,bool)));



  • }







  • FtpManager::~FtpManager()



  • {



  •     delete myFtp;



  • }







  • //停止Ftp动作



  • void FtpManager::S_abort()



  • {



  •     myFtp->abort();



  • }







  • //下载文件(当isRese==true为续传下载)



  • void FtpManager::S_dloadFile(QString _remoteFile,QString _localFile,bool isRese)



  • {



  •     m_File = new QFile(_localFile);







  •     if(!isRese)



  •     {



  •         qDebug() << tr("文件%1的普通下载... ...").arg(_remoteFile);



  •         if(m_File->open(QIODevice::WriteOnly))



  •         {



  •             m_IsOpenFile = true;



  •             myFtp->get(_remoteFile,m_File);



  •         }



  •         else



  •         {



  •             delete m_File;



  •             m_File = NULL;



  •             qDebug() << tr("本地文件%1打开失败!").arg(_localFile);



  •         }



  •     }



  •     else



  •     {



  •         qDebug() << tr("文件%1的续传下载... ...").arg(_remoteFile);



  •         if(m_File->open(QIODevice::Append))



  •         {



  •             m_IsOpenFile = true;



  •             myFtp->rawCommand(tr("REST %1").arg(m_File->size()));



  •             myFtp->m_isConLoad = true;          //设置当前现在为续传



  •             myFtp->get(_remoteFile,m_File);



  •         }



  •         else



  •         {



  •             delete m_File;



  •             m_File = NULL;



  •             qDebug() << tr("本地文件%1打开失败!").arg(_localFile);



  •         }



  •     }



  • }







  • //上传文件(当isRese==true为续传上传)



  • void FtpManager::S_uloadFile(QString _localFile,QString _remoteFile,bool isRese)



  • {



  •     m_File = new QFile(_localFile);







  •     if(m_File->open(QIODevice::ReadOnly))



  •     {



  •         m_IsOpenFile = true;



  •         if(!isRese)



  •         {



  •             qDebug() << tr("文件%1的普通上传... ...").arg(_localFile);



  •             myFtp->put(m_File,_remoteFile);                                     //上传



  •         }



  •         else



  •         {



  •             qDebug() << tr("文件%1的续传... ...").arg(_localFile);



  •             //在QFtp中定义续传方法



  •             myFtp->conPut(m_File,_remoteFile);                                  //续传



  •         }



  •     }



  •     else



  •     {



  •         delete m_File;



  •         m_File = NULL;



  •         qDebug() << tr("本地文件%1打开失败!").arg(_localFile);



  •     }



  • }







  • //更新进度条



  • void FtpManager::S_upDateProgress(qint64 _used, qint64 _total)



  • {



  •     int tmpVal = _used / (double)_total * 100;



  •     emit G_getProgressVal(tmpVal);



  • }







  • //ftp服务提示信息



  • void FtpManager::S_commandFinish(int tmp, bool en)



  • {



  •     Q_UNUSED(tmp);







  •     if(myFtp->currentCommand() == QFtp::ConnectToHost){







  •         if(en)



  •             qDebug() << (tr("连接服务器出现错误:%1").arg(myFtp->errorString()));







  •         else



  •         {



  •             qDebug() << (tr("连接到服务器成功"));



  •             myFtp->login(m_userName,m_passwd);                           //登陆服务器



  •         }



  •     }







  •     if (myFtp->currentCommand() == QFtp::Login){







  •         if(en)



  •             qDebug() << (tr("登录出现错误:%1").arg(myFtp->errorString()));







  •         else



  •             qDebug() << (tr("登录服务器成功"));







  •     }







  •     if (myFtp->currentCommand() == QFtp::Get)



  •     {







  •         if(en)



  •         {



  •             qDebug() << (tr("下载出现错误:%1").arg(myFtp->errorString()));



  •         }







  •         else



  •         {



  •             qDebug() << (tr("已经完成下载"));



  •             m_File->flush();



  •         }







  •         m_File->close();



  •         m_IsOpenFile = false;



  •         delete m_File;



  •         m_File = NULL;



  •     }



  •     else if(myFtp->currentCommand() == QFtp::Put)



  •     {







  •         if(en)



  •         {



  •             qDebug() << (tr("上传出现错误:%1").arg(myFtp->errorString()));



  •         }



  •         else



  •         {



  •             qDebug() << (tr("已经完成文件上传"));



  •         }







  •         m_File->close();



  •         m_IsOpenFile = false;



  •         delete m_File;



  •         m_File = NULL;



  •     }



  •     else if (myFtp->currentCommand() == QFtp::Close)



  •     {







  •         qDebug() << (tr("已经关闭连接"));







  •         if(m_IsOpenFile)



  •         {



  •             m_File->close();



  •             delete m_File;



  •             m_File = NULL;



  •         }



  •     }



  • }


测试用的小例子



  • #include "mainwindow.h"



  • #include "ui_mainwindow.h"







  • MainWindow::MainWindow(QWidget *parent) :



  •     QMainWindow(parent),



  •     ui(new Ui::MainWindow)



  • {



  •     ui->setupUi(this);



  •     manager = new FtpManager("192.168.136.144","zhj","123456",21,this);



  •     manager2 = new FtpManager("192.168.136.144","zhj","123456",21,this);



  •     connect(manager,SIGNAL(G_getProgressVal(int)),SLOT(S_updateProgess(int)));



  •     connect(manager2,SIGNAL(G_getProgressVal(int)),SLOT(S_updateProgess2(int)));



  • }







  • MainWindow::~MainWindow()



  • {



  •     delete ui;



  • }







  • //更新进度条







  • void MainWindow::S_updateProgess(int _val)



  • {







  •     ui->progressBar->setValue(_val);



  • }











  • //更新进度条



  • void MainWindow::S_updateProgess2(int _val)



  • {







  •     ui->progressBar_2->setValue(_val);



  • }











  • //普通下载



  • void MainWindow::on_downloadBn_clicked()



  • {



  •     manager->S_dloadFile("VisualStdio.Net2005_En.iso","G:/VisualStdio.Net2005_En.iso");



  • }







  • //普通上传



  • void MainWindow::on_uploadBn_clicked()



  • {



  •     manager->S_uloadFile("D:/QTWorkspace.zip","QTWorkspace.zip");



  • }







  • //下载(续传)



  • void MainWindow::on_downloadBn_2_clicked()



  • {



  •     manager2->S_dloadFile("VisualStdio.Net2005_En.iso","G:/VisualStdio.Net2005_En.iso",true);



  • }







  • //停止



  • void MainWindow::on_abort_clicked()



  • {



  •     manager2->S_abort();



  • }







  • //上传(续传)



  • void MainWindow::on_abort_2_clicked()



  • {



  •     manager2->S_uloadFile("D:/QTWorkspace.zip","QTWorkspace.zip",true);



  • }







  • //停止



  • void MainWindow::on_abort_3_clicked()



  • {



  •     manager->S_abort();



  • }


//普通文件上传

//普通文件下载


QFtp具有文件上传以及下载功能,

但是对于文件的续传支持上不好,因此 我使用Qt5.2.1编译器,从网络上下载了QFtp的实现,对其进行修改。目前为止,可以实现文件的续传功能。


1 个回复

倒序浏览
奈斯
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马