Qt编程9:QFtp断点续传(普通文件)

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

 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值