基于libssh2拷贝文件夹下所有文件到本地目录

  1. 基于libssh2,使用层次遍历的方式,从远端拷贝文件到本地目录,支持所有目录(等同于ssh -r效果)
#include <string>
#include <QString>
#include <libssh2.h>
#include <libssh2_sftp.h>

static QString sourceDir = "";
static std::queue<QString> que;
static std::vector<QString> vec;

int sftp_hierarchical_traversal() {
	std::queue<QString> emptyQue;
	std::swap(que, emptyQue);
	vec.clear();
	que.push(sourceDir);

	const char* username = "";
	const char* password = "";
	std::string clientAddress = "";
	const char* hostname = "";
	const char* remote_path = "";
	const char* local_path = "";
	int port = 22;
	struct sockaddr_in sin;
	unsigned long hostaddr;

	// 初始化 libssh2 库
	int rc = libssh2_init(0);
	if (rc != 0) {
		fprintf(stderr, "Failed to initialize libssh2\n");
		return 1;
	}

	// 连接到远程主机
	LIBSSH2_SESSION* session = libssh2_session_init();
	if (!session) {
		fprintf(stderr, "Failed to create SSH session\n");
		libssh2_exit();
		return 1;
	}

	hostaddr = inet_addr(hostname);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(22);
	sin.sin_addr.s_addr = hostaddr;
	// 创建socket
	int sock = socket(AF_INET, SOCK_STREAM, 0);//ws2_32.lib
	if (sock == -1) {
		std::cerr << "Failed to create socket" << std::endl;
		return 1;
	}

	if (::connect(sock, (struct sockaddr*)(&sin),
		sizeof(struct sockaddr_in)) != 0) {
		fprintf(stderr, "failed to connect!\n");
		return -1;
	}

	// 设置连接选项
	libssh2_session_set_blocking(session, 1);
	//rc = libssh2_session_startup(session, socket, username, hostname, port);
	rc = libssh2_session_handshake(session, sock);
	if (rc) {
		fprintf(stderr, "Failed to connect to %s:%d\n", hostname, port);
		libssh2_session_disconnect(session, "Failed to connect");
		libssh2_session_free(session);
		libssh2_exit();
		return 1;
	}

	// 使用用户名和密码进行身份验证
	if (libssh2_userauth_password(session, username, password)) {
		fprintf(stderr, "Authentication by password failed\n");
		libssh2_session_disconnect(session, "Authentication failed");
		libssh2_session_free(session);
		libssh2_exit();
		return 1;
	}

	// 初始化 SFTP 会话
	LIBSSH2_SFTP* sftp_session = libssh2_sftp_init(session);
	if (!sftp_session) {
		fprintf(stderr, "Failed to initialize SFTP session\n");
		libssh2_session_disconnect(session, "Failed to initialize SFTP session");
		libssh2_session_free(session);
		libssh2_exit();
		return 1;
	}

	while (!que.empty()) {
		QString remotePath = que.front();

		// Open the remote directory
		LIBSSH2_SFTP_HANDLE* sftp_handle;
		sftp_handle = libssh2_sftp_opendir(sftp_session, remotePath.toLocal8Bit().constData());
		if (!sftp_handle) {
			return 0;
		}

		// Iterate through the remote directory
		char buffer[512];
		while (1) {

			LIBSSH2_SFTP_ATTRIBUTES attrs;
			const char* filename;
			int rc = libssh2_sftp_readdir(sftp_handle, buffer, sizeof(buffer), &attrs);
			if (rc <= 0) {
				break;
			}
			if (strcmp(buffer, ".") == 0 || strcmp(buffer, "..") == 0) {
				continue;
			}
			filename = buffer;

			QString remoteFile = remotePath + "/" + filename;
			if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions)) {
				que.push(remoteFile);
			}
			else {
				vec.push_back(remoteFile);

				// 拷贝文件到本地
				LIBSSH2_SFTP_ATTRIBUTES attrs;
				libssh2_sftp_stat(sftp_session, remoteFile.toLocal8Bit().constData(), &attrs);
				if (attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS && LIBSSH2_SFTP_S_ISREG(attrs.permissions)) {
					QString local_file = remoteFile;
					local_file.replace(sourceDir, stateCache_imageDir);

					QFileInfo fileInfo(local_file);
					QDir directory = fileInfo.dir();
					// 判断文件对应的目录是否存在
					if (!directory.exists()) {
						QDir().mkpath(directory.absolutePath());
					}

					FILE* local_fp = fopen(local_file.toLocal8Bit().constData(), "wb");
					LIBSSH2_SFTP_HANDLE* remote_handle = libssh2_sftp_open(sftp_session, remoteFile.toLocal8Bit().constData(), LIBSSH2_FXF_READ, 0);
					size_t nread;
					char buffer[1024];
					do {
						nread = libssh2_sftp_read(remote_handle, buffer, sizeof(buffer));
						if (nread > 0) {
							fwrite(buffer, 1, nread, local_fp);
						}
					} while (nread > 0);
					fclose(local_fp);
					libssh2_sftp_close(remote_handle);
				}
			}
		}

		que.pop();
	}
}
  1. 直接调用ssh可执行文件的方式(需要在本机上生成公钥私钥,把公钥放到远端主机的.ssh目录下):
	//1. 拷贝数据
	//===========================================================
	// scp -r -i ~/Desktop/id_rsa -o "StrictHostKeyChecking no" root@192.168.226.41:/source ~/Desktop/
	// 创建QProcess对象
	QString appPath = QCoreApplication::applicationDirPath();
	// 设置要执行的命令行程序和参数
	QString program = "scp.exe";
	QStringList arguments;
	arguments << "-r" << QString::fromLocal8Bit("-i") << QString(appPath + "/id_rsa") << QString("-o") << QString("StrictHostKeyChecking no") << QString("root\@:/source ")) << stateCache_imageDir;
	qDebug() << appPath + "/id_rsa";
	// 启动外部进程
	QProcess process;
	process.start(program, arguments);
	process.waitForFinished(-1); // 等待进程执行完毧

	// 读取外部进程的输出
	QByteArray output = process.readAllStandardOutput();
	QByteArray error = process.readAllStandardError();
	LOG_ERROR(QString("Output : %1.").arg(QString(output)));
	LOG_ERROR(QString("Error : %1.").arg(QString(error)));
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是基于 `libssh` 库的 SFTP 登录和下载文件的 C 语言代码示例。请确保已经安装了 `libssh` 库,并且已经链接了 `-lssh` 库。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <libssh/libssh.h> #include <libssh/sftp.h> // 定义宏 #define SFTP_DIR_MODE 0755 #define SFTP_FILE_MODE 0644 // 定义 SFTP 连接信息结构体 typedef struct { ssh_session session; // SSH 会话 sftp_session sftp; // SFTP 会话 char *host; // 主机名 int port; // 端口号 char *username; // 用户名 char *password; // 登录密码 } SFTP_INFO; // 初始化 SFTP 会话 int sftp_init(SFTP_INFO *info) { // 连接 SSH 服务器 info->session = ssh_new(); if (info->session == NULL) { fprintf(stderr, "Error: Failed to create SSH session.\n"); return -1; } ssh_options_set(info->session, SSH_OPTIONS_HOST, info->host); ssh_options_set(info->session, SSH_OPTIONS_PORT, &info->port); if (ssh_connect(info->session) != SSH_OK) { fprintf(stderr, "Error: Failed to connect to SSH server.\n"); ssh_free(info->session); return -1; } // 登录 SSH 服务器 if (ssh_userauth_password(info->session, info->username, info->password) != SSH_AUTH_SUCCESS) { fprintf(stderr, "Error: Failed to authenticate with SSH server.\n"); ssh_disconnect(info->session); ssh_free(info->session); return -1; } // 打开 SFTP 会话 info->sftp = sftp_new(info->session); if (info->sftp == NULL) { fprintf(stderr, "Error: Failed to create SFTP session.\n"); ssh_disconnect(info->session); ssh_free(info->session); return -1; } if (sftp_init(info->sftp) != SSH_OK) { fprintf(stderr, "Error: Failed to initialize SFTP session.\n"); sftp_free(info->sftp); ssh_disconnect(info->session); ssh_free(info->session); return -1; } return 0; } // 关闭 SFTP 会话 void sftp_exit(SFTP_INFO *info) { sftp_free(info->sftp); ssh_disconnect(info->session); ssh_free(info->session); } // 下载文件 int sftp_download_file(SFTP_INFO *info, const char *remote_path, const char *local_path) { sftp_file file; int access_type = O_RDONLY; int mode = SFTP_FILE_MODE; int nread; char buffer[4096]; // 打开远程文件 file = sftp_open(info->sftp, remote_path, access_type, mode); if (file == NULL) { fprintf(stderr, "Error: Failed to open remote file '%s'.\n", remote_path); return -1; } // 创建本地文件 FILE *fp = fopen(local_path, "wb"); if (fp == NULL) { fprintf(stderr, "Error: Failed to create local file '%s'.\n", local_path); sftp_close(file); return -1; } // 读取远程文件内容并写入本地文件 while ((nread = sftp_read(file, buffer, sizeof(buffer))) > 0) { fwrite(buffer, 1, nread, fp); } // 关闭文件 fclose(fp); sftp_close(file); return 0; } // 主函数 int main() { SFTP_INFO info; memset(&info, 0, sizeof(info)); info.host = "192.168.1.100"; // 主机名 info.port = 22; // 端口号 info.username = "username"; // 用户名 info.password = "password"; // 登录密码 if (sftp_init(&info) != 0) { fprintf(stderr, "Error: Failed to initialize SFTP session.\n"); return -1; } if (sftp_download_file(&info, "/home/remote/file.txt", "/home/local/file.txt") != 0) { fprintf(stderr, "Error: Failed to download file.\n"); } sftp_exit(&info); return 0; } ``` 在上面的代码中,我们定义了 `SFTP_INFO` 结构体来存储 SFTP 连接信息,包括 SSH 会话、SFTP 会话、主机名、端口号、用户名和密码。然后我们定义了 `sftp_init` 函数来连接 SSH 服务器、登录 SSH 服务器并打开 SFTP 会话。接着我们定义了 `sftp_download_file` 函数来下载文件。该函数首先打开远程文件,然后创建本地文件,并读取远程文件内容并写入本地文件。最后我们在主函数中调用 `sftp_init` 和 `sftp_download_file` 函数,并在下载完成后调用 `sftp_exit` 函数关闭 SFTP 会话。 需要注意的是,在实际使用中,我们需要根据实际情况修改代码中的主机名、端口号、用户名和密码,以及远程文件和本地文件的路径。另外,在下载文件时,我们可以根据需要设置文件的访问模式和缓冲区大小。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值