Qt之QNetworkAccessManager 实现FTP文件上传/下载功能

简述 

        Qt5移除了QFtp API,原因是其实现质量,QNetworkAccessManager 可以用来提供 ftp url 的上传下载操作; 但是美中不足的是QNetworkAccessManager没有提供list()、cd()、remove()、mkdir()、rmdir()、rename() 和 rawCommand()等操作。

效果

代码 

        首先封装了类是为了方便调用,减少代码重复:

#ifndef MYFTPMANAGER_H
#define MYFTPMANAGER_H

#include <QUrl>
#include <QObject>
#include <QNetworkReply>
#include <QNetworkAccessManager>

class MyFtpManager : public QObject
{
    Q_OBJECT
public:
    explicit MyFtpManager(QObject *parent = 0);

    QNetworkReply *put(const QString &localPath, const QString &uploadPath);
    QNetworkReply *get(const QString &downloadPath, const QString &localPath);

    inline void setPort(int port) { url.setPort(port); }
    inline void setHost(const QString &host) { url.setHost(host); }
    inline void setPath(const QString &path) { url.setPath(path); }
    inline void setUserName(const QString &userName) { url.setUserName(userName); }
    inline void setPassword(const QString &password) { url.setPassword(password); }

public slots:
    void uploadFinished();
    void downloadFinished();
    void error(QNetworkReply::NetworkError error);

private:
    QUrl url;
    QString path;
    QNetworkAccessManager manager;
};

#endif // MYFTPMANAGER_H
#include "MyFtpManager.h"

#include <QFile>
#include <QNetworkRequest>

MyFtpManager::MyFtpManager(QObject *parent) :
    QObject(parent)
{
    // 设置协议
    url.setScheme("ftp");
}

QNetworkReply *MyFtpManager::put(const QString &localPath, const QString &uploadPath)
{
    // 文件是否可以打开
    QFile file(localPath);
    if (!file.open(QIODevice::ReadOnly))
        return NULL;

    // 设置上传路径
    url.setPath(uploadPath);

    QNetworkReply *pReply = manager.put(QNetworkRequest(url), file.readAll());
    connect(pReply, SIGNAL(finished()), SLOT(uploadFinished()));
    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
    return pReply;
}

QNetworkReply *MyFtpManager::get(const QString &downloadPath, const QString &localPath)
{
    // 记录要保存的位置
    path = localPath;

    // 设置下载路径
    url.setPath(downloadPath);

    QNetworkReply *pReply = manager.get(QNetworkRequest(url));
    connect(pReply, SIGNAL(finished()), SLOT(downloadFinished()));
    connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
    return pReply;
}

void MyFtpManager::uploadFinished()
{

}

void MyFtpManager::downloadFinished()
{
    QNetworkReply *pReply = qobject_cast<QNetworkReply *>(sender());
    if (pReply == NULL)
        return;

    // 如果有错误就不需要保存
    if (pReply->error() != QNetworkReply::NoError)
        return;

    // 写入文件
    QFile file(path);
    if (!file.open(QIODevice::WriteOnly))
        return;

    file.write(pReply->readAll());
    file.flush();
    file.close();
}

void MyFtpManager::error(QNetworkReply::NetworkError error)
{
    qDebug() << error;
}

        在MainWnd中声明一个成员变量manager,然后在造函数中初始化它:

    manager.setHost("192.168.43.5");    // 设置服务器IP地址
    manager.setPort(21);                // 设置端口
    manager.setUserName("zhangsan");    // 设置用户名
    manager.setPassword("000000");      // 设置密码

        在点击上传按钮时,把某一个路径下的所有图片都上传到FTP服务器指定的路径下:

void MainWnd::on_tbUpload_clicked()
{
    QDir dir("F:/Pictrue");

    QStringList filter;
    filter << "*.jpg" << "*.bmp" << "*.png";
    QList<QFileInfo> list = QList<QFileInfo>(dir.entryInfoList(filter));

    foreach (QFileInfo info, list)
    {
        QNetworkReply *pReply = manager.put(info.filePath(), QString("/picture/%1").arg(info.fileName()));
        connect(pReply, SIGNAL(uploadProgress(qint64,qint64)), SLOT(uploadProgress(qint64,qint64)));
    }
}

        在点击下载按钮时,只是单纯的下载某一张图像到程序根目录:

void MainWnd::on_tbDownload_clicked()
{
    QNetworkReply *pReply = manager.get("/picture/DSCF21061.jpg", "./DSCF21061.jpg");
    connect(pReply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(downloadProgress(qint64,qint64)));
}

         然后就是通过信号槽更新进度条:

void MainWnd::uploadProgress(qint64 byteSend, qint64 byteTotal)
{
    ui->pgbUpload->setMaximum(byteTotal);
    ui->pgbUpload->setValue(byteSend);
}

void MainWnd::downloadProgress(qint64 byteSend, qint64 byteTotal)
{
    ui->pgbDownload->setMaximum(byteTotal);
    ui->pgbDownload->setValue(byteSend);
}

注意

        1. 使用QUrl时需要设置'ftp'协议,否则会提示以下的错误:

        2. 在点击上传时,要上传的目录必须存在,也就是说这里上传的目录"/picture"是事先在服务器创建好的;如果服务器中不存在这个目录它不会主动帮你创建,会提示以下的错误:

QNetworkReply::NetworkError(ContentAccessDenied)

        源码下载1(折扣):https://item.taobao.com/item.htm?ft=t&id=702584276003

        源码下载2(无折扣):https://download.csdn.net/download/Ilson_/19418875

        Windows下FTP服务器搭建:https://blog.csdn.net/Ilson_/article/details/97818689

        QFtp在客户端实现给服务器一次性创建多级目录:https://blog.csdn.net/Ilson_/article/details/98654137

        QFtp实现文件上传、下载、新建文件夹、重命名、删除和刷新等功能:https://blog.csdn.net/Ilson_/article/details/98371848

  • 19
    点赞
  • 155
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 47
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ilson_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值