#include "QtFtp.h" #include "LightLog.h" #include /* 构造函数 */ QtFtp::QtFtp(QObject *parent) { /* 设置协议 */ m_url.setScheme("ftp"); /* 设置超时定时器 */ m_timer.setTimerType(Qt::PreciseTimer); m_timer.setSingleShot(true); } QtFtp::~QtFtp() { if(m_file.isOpen()) { m_file.close(); } if(m_reply != nullptr) { m_reply->deleteLater(); m_reply = nullptr; } } /* 设置目标主机IP和端口 */ void QtFtp::setHostAndPort(const QString &host, int port) { m_url.setHost(host); m_url.setPort(port); } /* 设置目标设备的用户名和密码 */ void QtFtp::setUserPasswd(const QString &user, const QString &pw) { m_url.setUserName(user); m_url.setPassword(pw); } /** * @brief 上传文件 * @param file 要上传的文件名 * @param path 目标计算机存放文件的路径 */ void QtFtp::putFile(const QString &fileName, const QString &farPath) { m_isFinished = false; m_result = false; QFile file(fileName); file.open(QFile::ReadOnly); QByteArray ba = file.readAll(); file.close(); m_url.setPath(farPath); m_reply = m_manager.put(QNetworkRequest(m_url),ba); /* 将信号进行一次转发 */ connect(m_reply,SIGNAL(uploadProgress(qint64,qint64)),this,SIGNAL(signal_uploadProgress(qint64,qint64))); /* 连接信号和槽 */ connect(m_reply,SIGNAL(finished()),this,SLOT(do_uploadFinished())); connect(m_reply,SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(do_uploadProgress(qint64,qint64))); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SIGNAL(signal_error(QNetworkReply::NetworkError))); #endif } /** * @brief 重载函数,上传文件,直接上传内存数据 * * @param data 需要上传的数据 * @param farPath 远程文件名 */ void QtFtp::putFile(const QByteArray& data,const QString& farPath) { m_isFinished = false; m_result = false; m_url.setPath(farPath); m_reply = m_manager.put(QNetworkRequest(m_url),data); /* 将信号进行一次转发 */ connect(m_reply,SIGNAL(uploadProgress(qint64,qint64)),this,SIGNAL(signal_uploadProgress(qint64,qint64))); /* 连接信号和槽 */ connect(m_reply,SIGNAL(finished()),this,SLOT(do_uploadFinished())); connect(m_reply,SIGNAL(uploadProgress(qint64,qint64)),this,SLOT(do_uploadProgress(qint64,qint64))); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SIGNAL(signal_error(QNetworkReply::NetworkError))); #endif } /** * @brief QtFtp::getFile * @param fileName 本机文件路径和文件名 * @param path 目标文件路径 */ void QtFtp::getFile(const QString &fileName,const QString &srcPath) { m_isFinished = false; m_result = false; m_file.setFileName(fileName); if(!m_file.open(QFile::WriteOnly | QFile::Truncate)) { LOG_WARN("open file failed , file path : " + fileName); return; } m_url.setPath(srcPath); m_reply = m_manager.get(QNetworkRequest(m_url)); /* 转发信号 */ connect(m_reply,SIGNAL(downloadProgress(qint64,qint64)),this,SIGNAL(signal_downloadProgress(qint64,qint64))); /* 连接信号和槽 */ connect(m_reply,SIGNAL(finished()),this,SLOT(do_downloadFinished())); connect(m_reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(do_downloadProgress(qint64,qint64))); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SIGNAL(signal_error(QNetworkReply::NetworkError))); #endif } /* 下载文件,直接下载到内存 */ void QtFtp::getFile(QByteArray& data,const QString& srcPath) { m_isFinished = false; m_result = false; m_downloadData = &data; m_url.setPath(srcPath); m_reply = m_manager.get(QNetworkRequest(m_url)); /* 转发信号 */ connect(m_reply,SIGNAL(downloadProgress(qint64,qint64)),this,SIGNAL(signal_downloadProgress(qint64,qint64))); /* 连接信号和槽 */ connect(m_reply,SIGNAL(finished()),this,SLOT(do_downloadFinishedToData())); connect(m_reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(do_downloadProgress(qint64,qint64))); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SIGNAL(signal_error(QNetworkReply::NetworkError))); #endif } /** * @brief 等待完成,同时设置超时时间,超时后,断开reply的信号和槽的连接 * 参数设置为0表示查询是否完成,设置为-1表示一直等待 * * @param msecs 超时时间 * @arg -1 一直等待,将会阻塞在这里 * @arg 0 查询是否完成 * @arg 正整数,等待完成的时间,设置完成之后再次设置,会覆盖之前的设置 * @return true 上传或下载完成 * @return false 上传或下载进行中 */ bool QtFtp::waitFinished(int msecs) { if(msecs == 0) { return m_isFinished; } else if(msecs == -1) { QEventLoop loop; connect(this, &QtFtp::signal_uploadState, &loop, &QEventLoop::quit); connect(this, &QtFtp::signal_downloadState, &loop, &QEventLoop::quit); loop.exec(); return true; } else if (msecs > 0) { m_timer.start(msecs); return m_isFinished; } return m_isFinished; } /** * @brief 获取结果 * * @return int * @arg -1 上传或下载失败 * @arg 0 上传或下载成功 */ bool QtFtp::getResult() { return m_result; } /* 上传完成 */ void QtFtp::do_uploadFinished() { if(m_reply->error() == QNetworkReply::NoError) { m_result = true; emit signal_uploadState(true); LOG_INFO("----- FTP upload success -----"); } else { LOG_WARN("FTP upload failed : " + m_reply->errorString()); emit signal_uploadState(false); } m_reply->deleteLater(); m_reply = nullptr; m_isFinished = true; } /* 创建目录 */ bool QtFtp::createDir(const QString& path) { m_isFinished = false; m_result = false; QNetworkRequest request; QUrl url; url.setHost(m_url.host()); url.setPort(m_url.port()); url.setUserName(m_url.userName()); url.setPassword(m_url.password()); url.setPath(path); LOG_DEBUG("create dir : " + url.path()); request.setUrl(url); request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); QByteArray data; data.append("command=MKD"); m_reply = m_manager.post(request,data); /* 连接信号和槽 */ connect(m_reply,SIGNAL(finished()),this,SLOT(do_finished())); #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) connect(m_reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SIGNAL(signal_error(QNetworkReply::NetworkError))); #endif return true; } /* 完成,保存文件 */ void QtFtp::do_downloadFinished() { if(m_reply->error() == QNetworkReply::NoError) { m_file.write(m_reply->readAll()); m_file.flush(); /* 刷新文件,写入硬盘 */ emit signal_downloadState(true); m_result = true; LOG_DEBUG("----- FTP download success -----"); }else { LOG_WARN("FTP download failed:" + m_reply->errorString()); /* 下载失败就删除创建的文件 */ m_file.remove(); emit signal_downloadState(false); } m_file.close(); m_reply->deleteLater(); m_reply = nullptr; m_isFinished = true; } /* 下载完成,保存数据 */ void QtFtp::do_downloadFinishedToData() { if(m_reply->error() == QNetworkReply::NoError) { *m_downloadData = m_reply->readAll(); emit signal_downloadState(true); m_result = true; LOG_DEBUG("----- FTP download success -----"); }else { LOG_WARN("FTP download failed:" + m_reply->errorString()); emit signal_downloadState(false); } m_downloadData = nullptr; m_reply->deleteLater(); m_reply = nullptr; m_isFinished = true; } /* 上传进度 */ void QtFtp::do_uploadProgress(qint64 bytesSent, qint64 bytesTotal) { LOG_DEBUG("sent / total : " + QString::number(bytesSent) + " / " + QString::number(bytesTotal)); } /* 下载进度 */ void QtFtp::do_downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { LOG_DEBUG("received / total : " + QString::number(bytesReceived) + " / " + QString::number(bytesTotal)); } /* ftp其他任务完成槽函数 */ void QtFtp::do_finished() { m_isFinished = true; if(m_reply->error() == QNetworkReply::NoError) { LOG_INFO("----- FTP operation success -----"); m_result = true; }else { LOG_WARN("FTP operation failed : " + m_reply->errorString()); m_result = false; } m_reply->deleteLater(); m_reply = nullptr; m_isFinished = true; } /* ftp发送错误槽函数 */ #if defined (QT_VERSION) && QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) void QtFtp::do_ftpReplyError(QNetworkReply::NetworkError error) { if(error == QNetworkReply::NoError) { LOG_INFO("FTP发送成功"); } else { LOG_WARN("FTP发送失败:" + QString::number(error)); } } #endif