首页 > 其他分享 >使用QNetworkAccessManager实现FTP上传下载功能

使用QNetworkAccessManager实现FTP上传下载功能

时间:2024-08-07 16:56:33浏览次数:9  
标签:FTP const QNetworkAccessManager pFile void pReply QString strRemoteDir 上传下载

自己写了一份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

相关文章

  • 金融行业到底该选择什么样的FTP替代方案?
    2018年以来,受“华为、中兴事件”影响,我国科技尤其是上游核心技术受制于人的现状对我国经济发展提出了严峻考验。在全球产业从工业经济向数字经济升级的关键时期,中国明确“数字中国”建设战略,抢占数字经济产业链制高点。在执行层面,从最关系国计民生的行业开始,也就是“2+8+N”......
  • 文件系统 FTP Ubuntu 安装入门介绍
    文件服务系列文件存储服务系统(FileStorageServiceSystem)-00-文件服务器是什么?为什么需要?文件存储服务系统(FileStorageServiceSystem)-01-常见的文件协议介绍文件系统FTPUbuntu安装入门介绍文件存储服务系统(FileStorageServiceSystem)-02-SFTP协议介绍分布式文件服......
  • 记录一次CentOS/Linux下安装vsftp服务器的过程
    1安装ftp软件yuminstallvsftpd*-y2配置服务启动#启用firewalld服务systemctlstartvsftpd.service#开启vsftpd服务这条命令设置firewalld服务在系统启动时自动启动。systemctlenable命令用于管理系统服务的启动和停止配置。启用服务后,它会在每次系统启动时......
  • linux之FTP服务vsftpd和pure-ftpd常用配置
    vsftpdvsftpd介绍部分参考自vsftpd操作手册-完整版-HOsystem-博客园(cnblogs.com)vsftpd认证模式匿名开放模式:是最不安全的一种认证模式,任何人都可以无须密码验证而直接登录到FTP服务器。本地用户模式:是通过Linux系统本地的账户密码信息进行认证的模式,相较于匿名开......
  • 比网盘、FTP更好用的数据摆渡工具是什么?
    企业进行网络隔离后,数据在隔离网间交换时就产生了数据摆渡需求,常见的数据摆渡工具包括移动U盘、网盘、FTP等,企业通常选择网盘、FTP来进行日常的数据摆渡操作。但网盘和FTP在数据摆渡上均存在不同程度的缺陷,具体表现在:数据量限制:网盘一般面向办公文档型数据,系统往往不具备发送大......
  • C#对FTP进行上传下载操作
    privatevoidbt_ftp_Click(objectsender,EventArgse){try{引用WinSCP类//SetupsessionoptionsSessionOptionssessionOptions=newSessionOptions{Protocol=Protocol.Ftp,HostName="ftp域名&q......
  • vsftpd
    vsftpd一、安装yum-yinstallvsftpd二、配置vsftpdegrep-v"^#|^$"/etc/vsftpd/vsftpd.conf#允许匿名用户登录,默认NOanonymous_enable=YES#指定匿名用户的根目录anon_root=/mnt/rhd/ftp/ftpuser#允许本地用户登录local_enable=YES#允许写入操作write_enab......
  • FTP服务器搭建及C#实现FTP文件操作
    FTP服务器搭建及C#实现FTP文件操作1、搭建FTP服务器(以win10为例)FTP服务器搭建及C#实现FTP文件操作_c#ftp-CSDN博客2、代码usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Net;usingSystem.Text;usingSystem.Threading.Tasks;namesp......
  • sftp文件上传下载方法
    随着信息化、数字化的发展,企业对数据安全及应用安全意识普遍加强,在数据文件传输过程中,一般建议使用sftp协议进行文件传输,sftp文件操作脚本如下:sftp操作主要有三种方式,分别是sftp客户端操作、sdk操作、操作系统命令操作,针对sdk方式。一、sdk方式:<!--sftp集成jar--><dependen......
  • vsftpd搭建FTP服务器 - 虚拟用户
    命令记录$sudoaptinstallvsftpddb-util$sudonano/etc/vsftpd.conf$sudonano/etc/vsftpd/vsftpd-virtual-users.txt$sudodb_load-T-thash-f/etc/vsftpd/vsftpd-virtual-users.txt/etc/vsftpd/vsftpd-virtual-users.dbls/etc/vsftpd/vsftpd-virtual-use......