自己写了一份FTP的代码,可以上传下载单文件,上传下载多文件,上传目录所有文件,但是下载目录的功能有问题,接口里代码规范也没做(如果有大佬提供修改方案就更好了),代码直接复制可用,留给有需要的人。
#pragma once
#include <QObject>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QFile>
#include <QTcpSocket>
#include <QMap>
class CFtpMgr : public QObject
{
Q_OBJECT
public:
CFtpMgr(QObject* parent = nullptr);
~CFtpMgr();
void SetFtpAuthority(const QString& strHost, const QString& strName, const QString& strPassword, quint16 nPort = 21);
void DownloadFile(const QString& strRemoteFilePath, const QString& strLocalDir);
void UploadFile(const QString& strLocalFilePath, const QString& strRemoteDir);
void DownloadFiles(const QStringList& listRemoteFilePaths, const QString& strLocalDir);
void UploadFiles(const QStringList& listLocalFilePaths, const QString& strRemoteDir);
void DownloadDir(const QString& strRemoteDir, const QString& strLocalDir);
void UploadDir(const QString& strLocalDir, const QString& strRemoteDir);
signals:
void SigDownloadProgress(qint64 nReceived, qint64 nTotal);
void SigUploadProgress(qint64 nReceived, qint64 nTotal);
public slots:
void SlotDownloadProgress(qint64 nReceived, qint64 nTotal);
void SlotDownloadError(QNetworkReply::NetworkError eError);
void SlotDownloadFinished();
void SlotUploadProgress(qint64 nReceived, qint64 nTotal);
void SlotUploadError(QNetworkReply::NetworkError eError);
void SlotUploadFinished();
private:
void EnsureRemotePathExists(const QString& strRemoteDir);
void RecursiveDownloadDir(const QString& strRemoteDir, const QString& strLocalDir);
void RecursiveUploadDir(const QString& strLocalDir, const QString& strRemoteDir);
private:
QUrl m_url;
QNetworkAccessManager m_manager;
QTcpSocket m_socket;
QMap<QNetworkReply*, QFile*> m_mapGetReplies;
QMap<QNetworkReply*, QFile*> m_mapPutReplies;
};
#include "FtpMgr.h"
#include <QDir>
#include <QDebug>
#include <QTcpServer>
CFtpMgr::CFtpMgr(QObject* parent)
: QObject(parent)
{
m_url.setScheme("ftp");
}
CFtpMgr::~CFtpMgr()
{
qDeleteAll(m_mapGetReplies);
qDeleteAll(m_mapPutReplies);
}
void CFtpMgr::SetFtpAuthority(const QString& strHost, const QString& strName, const QString& strPassword, quint16 nPort)
{
m_url.setHost(strHost);
m_url.setUserName(strName);
m_url.setPassword(strPassword);
m_url.setPort(nPort);
}
void CFtpMgr::DownloadFile(const QString& strRemoteFilePath, const QString& strLocalDir)
{
const QString strSaveFileName = strLocalDir + "/" + QFileInfo(strRemoteFilePath).fileName();
QFile* pFile = new QFile(strSaveFileName, this);
if (pFile->open(QIODevice::WriteOnly))
{
m_url.setPath(strRemoteFilePath);
QNetworkReply* pReply = m_manager.get(QNetworkRequest(m_url));
m_mapGetReplies[pReply] = pFile;
connect(pReply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(SlotDownloadProgress(qint64, qint64)));
connect(pReply, SIGNAL(finished()), this, SLOT(SlotDownloadFinished()));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(SlotDownloadError(QNetworkReply::NetworkError)));
}
else
{
delete pFile;
}
}
void CFtpMgr::UploadFile(const QString& strLocalFilePath, const QString& strRemoteDir)
{
EnsureRemotePathExists(strRemoteDir);
QFile* pFile = new QFile(strLocalFilePath, this);
if (pFile->open(QIODevice::ReadOnly))
{
const QString strSaveFileName = strRemoteDir + "/" + QFileInfo(strLocalFilePath).fileName();
m_url.setPath(strSaveFileName);
QNetworkReply* pReply = m_manager.put(QNetworkRequest(m_url), pFile);
m_mapPutReplies[pReply] = pFile;
connect(pReply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(SlotUploadProgress(qint64, qint64)));
connect(pReply, SIGNAL(finished()), this, SLOT(SlotUploadFinished()));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(SlotUploadError(QNetworkReply::NetworkError)));
}
else
{
delete pFile;
}
}
void CFtpMgr::DownloadFiles(const QStringList& listRemoteFilePaths, const QString& strLocalDir)
{
foreach(const QString & remoteFilePath, listRemoteFilePaths)
{
DownloadFile(remoteFilePath, strLocalDir);
}
}
void CFtpMgr::UploadFiles(const QStringList& listLocalFilePaths, const QString& strRemoteDir)
{
EnsureRemotePathExists(strRemoteDir);
foreach(const QString & localFilePath, listLocalFilePaths)
{
UploadFile(localFilePath, strRemoteDir);
}
}
void CFtpMgr::DownloadDir(const QString& strRemoteDir, const QString& strLocalDir)
{
QDir localDir(strLocalDir);
if (!localDir.exists())
{
localDir.mkpath(".");
}
RecursiveDownloadDir(strRemoteDir, strLocalDir);
}
void CFtpMgr::UploadDir(const QString& strLocalDir, const QString& strRemoteDir)
{
RecursiveUploadDir(strLocalDir, strRemoteDir);
}
void CFtpMgr::EnsureRemotePathExists(const QString& strRemoteDir)
{
m_socket.connectToHost(m_url.host(), m_url.port(21));
if (m_socket.waitForConnected())
{
m_socket.write("USER " + m_url.userName().toUtf8() + "\r\n");
m_socket.waitForReadyRead();
m_socket.write("PASS " + m_url.password().toUtf8() + "\r\n");
m_socket.waitForReadyRead();
m_socket.write("MKD " + strRemoteDir.toUtf8() + "\r\n");
m_socket.waitForReadyRead();
m_socket.disconnectFromHost();
}
}
void CFtpMgr::RecursiveDownloadDir(const QString& strRemoteDir, const QString& strLocalDir)
{
// 接口不可用
return;
// 以下为测试代码
m_url.setPath(m_url.path() + strRemoteDir);
QNetworkRequest listRequest(m_url);
QNetworkReply* listReply = m_manager.get(listRequest);
connect(listReply, &QNetworkReply::finished, listReply, [=]()
{
if (listReply->error() == QNetworkReply::NoError)
{
QString list = listReply->readAll();
QStringList lines = list.split("\n");
QStringList remoteFiles;
QStringList remoteDirs;
for (const QString& line : lines)
{
if (line.trimmed().isEmpty())
{
continue;
}
// Assuming Unix-style listing
char entryType = line.at(0).toLatin1();
QString entryPath = line.mid(55).trimmed();
if (entryType == '-')
{
remoteFiles.append(entryPath);
}
else if (entryType == 'd')
{
remoteDirs.append(entryPath);
}
}
QStringList remoteFilePaths;
for (const QString& remoteFile : remoteFiles)
{
remoteFilePaths.append(strRemoteDir + remoteFile);
}
DownloadFiles(remoteFilePaths, strLocalDir);
for (const QString& remoteDir : remoteDirs)
{
QString subRemoteFolderPath = strRemoteDir + remoteDir + "/";
QString subLocalFolderPath = strLocalDir + remoteDir + "/";
RecursiveDownloadDir(subRemoteFolderPath, subLocalFolderPath);
}
}
else
{
qDebug() << "Error listing directory:" << listReply->errorString();
}
listReply->deleteLater();
});
}
void CFtpMgr::RecursiveUploadDir(const QString& strLocalDir, const QString& strRemoteDir)
{
QDir localDir(strLocalDir);
if (!localDir.exists())
{
return;
}
EnsureRemotePathExists(strRemoteDir);
QFileInfoList fileInfoList = localDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo& fileInfo : fileInfoList)
{
QString localPath = fileInfo.absoluteFilePath();
QString remotePath = strRemoteDir + "/" + fileInfo.fileName();
if (fileInfo.isDir())
{
RecursiveUploadDir(localPath, remotePath);
}
else if (fileInfo.isFile())
{
UploadFile(localPath, strRemoteDir);
}
}
}
void CFtpMgr::SlotDownloadProgress(qint64 nReceived, qint64 nTotal)
{
emit SigDownloadProgress(nReceived, nTotal);
}
void CFtpMgr::SlotDownloadError(QNetworkReply::NetworkError eError)
{
qDebug() << "Download Error: " << eError;
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
if (pReply)
{
if (m_mapGetReplies.contains(pReply))
{
QFile* pFile = m_mapGetReplies.value(pReply);
if (pFile)
{
pFile->close();
delete pFile;
}
m_mapGetReplies.remove(pReply);
}
pReply->deleteLater();
}
}
void CFtpMgr::SlotDownloadFinished()
{
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
if (pReply)
{
if (m_mapGetReplies.contains(pReply))
{
QFile* pFile = m_mapGetReplies.value(pReply);
if (pFile)
{
pFile->write(pReply->readAll());
pFile->close();
delete pFile;
}
m_mapGetReplies.remove(pReply);
}
pReply->deleteLater();
}
}
void CFtpMgr::SlotUploadProgress(qint64 nReceived, qint64 nTotal)
{
emit SigUploadProgress(nReceived, nTotal);
}
void CFtpMgr::SlotUploadError(QNetworkReply::NetworkError eError)
{
qDebug() << "Upload Error: " << eError;
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
if (pReply)
{
if (m_mapPutReplies.contains(pReply))
{
QFile* pFile = m_mapPutReplies.value(pReply);
if (pFile)
{
pFile->close();
delete pFile;
}
m_mapPutReplies.remove(pReply);
}
pReply->deleteLater();
}
}
void CFtpMgr::SlotUploadFinished()
{
QNetworkReply* pReply = qobject_cast<QNetworkReply*>(sender());
if (pReply)
{
if (m_mapPutReplies.contains(pReply))
{
QFile* pFile = m_mapPutReplies.value(pReply);
if (pFile)
{
pFile->close();
delete pFile;
}
m_mapPutReplies.remove(pReply);
}
pReply->deleteLater();
}
}
标签:FTP,const,QNetworkAccessManager,pFile,void,pReply,QString,strRemoteDir,上传下载
From: https://blog.csdn.net/m0_59119702/article/details/140996168