现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

QFtp实现断点续传普通文件

2015-11-14 14:27 工业·编程 ⁄ 共 6912字 ⁄ 字号 暂无评论

首先明确一点:实现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的实现,对其进行修改。目前为止,可以实现文件的续传功能。

作者:jhe_zhang

给我留言

留言无头像?