SSH连接SFTP传输:如何使用libssh库在windows环境下进行(文件、文件夹)传 ...

打印 上一主题 下一主题

主题 1039|帖子 1039|积分 3117

由于windows上的编译器一般都是没有libssh库的,所以如何我们想要使用libssh库那么我们将会使用cmake来编译libssh官网给出的源代码
  libssh库下载地址:https://www.libssh.org/files/

配置环境

我们在编译libssh库之前需要先配置一些环境:


  • a) 安装 Visual Studio 大概 MinGW
  • b) 安装OpenSSL http://slproweb.com/products/Win32OpenSSL.html 到 C:\Program Files
  • c) 安装zlib http://zlib.net/zlib128-dll.zip 到 C:\Program Files
  • d) 安装CMake http://cmake.org/cmake/resources/software.html
   有些库需要将其.dll加入环境变量,具体可自行探索
  cmake编译libssh

解压压缩包,进入目录,在当前页面右键打开终端

执行以下命令:
  1. mkdir build
  2. cd build
  3. cmake ..
复制代码
  假如出现一些报错很可能是配置环境的标题,可以观察报错信息逐一办理
  打开libssh.sln项目(使用cmake编译的编译器与打开的编译器需一致)

将ssh设为启动项目

Ctrl + B天生办理项目,天生dll与lib文件

如何使用天生的dll与lib文件

配置lib 方法一

打开vs工程 -》 项目 -》 属性

  • 将头文件也就是进入include下的路径添加进入附加包罗目录
    G:\xxx\libssh-0.10.0\include

  • 将.lib文件所在目录添加进入附加库目录
    G:\xxx\libssh-0.10.0\build\src\Debug

  • 将ssh.lib添加进入附加依赖项

配置lib 方法二

将ssh.lib文件复制到当前项目所在路径下

将ssh.lib导入项目即可,同理头文件也可直接复制进入项目路径



  • 假如是第一种方法,头文件引入可以#include <libssh/libssh.h> #include <libssh/sftp.h>
  • 假如是第二种方法,头文件引入必须#include "libssh/libssh.h" #include "libssh/sftp.h"
假如编译报错缺少这个文件libssh_version.h
这个文件在这个路径下G:\xxx\libssh-0.10.0\build\include\libssh,可以直接复制到libssh/下使用

配置dll方法一 将dll配置进入环境变量

点击此电脑 -》右键属性 -》 点击高级系统设置


将dll文件所在路径添加进入环境变量
G:\xxx\libssh-0.10.0\build\src\Debug


配置dll方法二 在编译过后将dll直接与可执行文件.exe文件放在同一目录下

   要使得用libssh库的项目能通过编译,需要将头文件以及.lib配置进入项目
    假如出现__imp__ xxx类型的链接错误很有很可能是当前项目是X86环境,而libssh库是X64的库,需要将vs执行环境改为X64
  传输文件、文件夹代码(适配windows)

  1. int sftp_normal_upload(ssh_session session, sftp_session sftp, const char* local_file_path, const char* remote_file_path)
  2. {
  3.     sftp_file file = sftp_open(sftp, remote_file_path, O_WRONLY | O_CREAT, 0666);
  4.     if (!file) {
  5.         fprintf(stderr, "Failed to open remote file: %s:sftp_get_error(%d)\n", remote_file_path, sftp_get_error(sftp));
  6.         fprintf(stderr, "Can't create directory: %s\n", ssh_get_error(session));
  7.         return -1;
  8.     }
  9.     FILE* local_file = fopen(local_file_path, "rb");
  10.     if (!local_file) {
  11.         fprintf(stderr, "Failed to open local file: %s\n", local_file_path);
  12.         sftp_close(file);
  13.         return -1;
  14.     }
  15.     // 上传文件内容
  16.     char buffer[1024];
  17.     size_t bytes_read;
  18.     while ((bytes_read = fread(buffer, 1, sizeof(buffer), local_file)) > 0) {
  19.         sftp_write(file, buffer, bytes_read);
  20.     }
  21.     fclose(local_file);
  22.     sftp_close(file);
  23.     return 1;
  24. }
  25. int sftp_recursive_upload(ssh_session session, sftp_session sftp, const char* local_path, const char* remote_path) {
  26.     // 计算转换后的宽字符所需缓冲区大小
  27.     int bufferSize_local = MultiByteToWideChar(CP_ACP, 0, local_path, -1, NULL, 0);
  28.     int bufferSize_remote = MultiByteToWideChar(CP_ACP, 0, remote_path, -1, NULL, 0);
  29.     // 分配缓冲区
  30.     wchar_t* local_path_to_wchar = (wchar_t*)malloc(bufferSize_local * sizeof(wchar_t));
  31.     wchar_t* remote_path_to_wchar = (wchar_t*)malloc(bufferSize_remote * sizeof(wchar_t));
  32.     if (local_path_to_wchar == NULL || local_path_to_wchar == NULL) {
  33.         fprintf(stderr, "Failed to memory\n");
  34.         // 处理内存分配失败的情况
  35.         return -1;
  36.     }
  37.     // 执行转换
  38.     MultiByteToWideChar(CP_ACP, 0, local_path, -1, local_path_to_wchar, bufferSize_local);
  39.     MultiByteToWideChar(CP_ACP, 0, remote_path, -1, remote_path_to_wchar, bufferSize_remote);
  40.     //给local_path追加通配符
  41.     const wchar_t* str = L"\\*";
  42.     wchar_t local_current[MAX_PATH];
  43.     if (wcslen(local_path_to_wchar) + 3 >= MAX_PATH - 1)
  44.     {
  45.         fprintf(stderr, "Failed to strcat wildcard character\n");
  46.         return -1;
  47.     }
  48.     // 将str1复制到result中
  49.     wcscpy(local_current, local_path_to_wchar);
  50.     // 追加str2到result中
  51.     wcscat(local_current, str);
  52.     // 打开本地目录
  53.     WIN32_FIND_DATA FindFileData;
  54.     HANDLE hFind = INVALID_HANDLE_VALUE;
  55.     hFind = FindFirstFile(local_current, &FindFileData);
  56.     if (hFind == INVALID_HANDLE_VALUE) {
  57.         fprintf(stderr, "Failed to open local directory: %s\n", local_current);
  58.         return -1;
  59.     }
  60.     // 创建服务器目录
  61.     sftp_mkdir(sftp, remote_path, 0777);
  62.     // 遍历本地目录项
  63.     do {
  64.         if (wcscmp(FindFileData.cFileName, L".") != 0 && wcscmp(FindFileData.cFileName, L"..") != 0) {
  65.             // 构造全路径
  66.             wchar_t local_file_path[MAX_PATH];
  67.             _snwprintf(local_file_path, sizeof(local_file_path), L"%s\\%s", local_path_to_wchar, FindFileData.cFileName);
  68.             wchar_t remote_file_path[MAX_PATH];
  69.             _snwprintf(remote_file_path, sizeof(remote_file_path), L"%s/%s", remote_path_to_wchar, FindFileData.cFileName);
  70.             // 将宽字符字符串转换为多字节字符字符串
  71.             char local_next[MAX_PATH];
  72.             char remote_next[MAX_PATH];
  73.             if (wcstombs(local_next, local_file_path, sizeof(local_next)) == (size_t)-1 ||
  74.                 wcstombs(remote_next, remote_file_path, sizeof(remote_next)) == (size_t)-1) {
  75.                 fprintf(stderr, "wchar_t conversion to char failed\n");
  76.                 return -1;
  77.             }
  78.             // 如果本地条目是一个目录,递归上传它
  79.             if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  80.                 sftp_recursive_upload(session, sftp, local_next, remote_next);
  81.             }
  82.             else { // 如果本地条目是一个普通文件,上传它
  83.                 sftp_normal_upload(session, sftp, local_next, remote_next);
  84.             }
  85.         }
  86.     } while (FindNextFile(hFind, &FindFileData) != 0);
  87.     free(local_path_to_wchar);
  88.     free(remote_path_to_wchar);
  89.     FindClose(hFind);
  90.     return 1;
  91. }
  92. ssh_session ssh_create(const char* target_host, const char* target_username)
  93. {
  94.     ssh_session session;
  95.     // 连接SSH会话
  96.     session = ssh_new();
  97.     if (!session) {
  98.         fprintf(stderr, "Failed to create SSH session\n");
  99.         return NULL;
  100.     }
  101.     ssh_options_set(session, SSH_OPTIONS_HOST, target_host);
  102.     ssh_options_set(session, SSH_OPTIONS_USER, target_username);
  103.     if (ssh_connect(session) != SSH_OK) {
  104.         fprintf(stderr, "Failed to connect to SSH session: %s\n", ssh_get_error(session));
  105.         ssh_free(session);
  106.         return NULL;
  107.     }
  108.     return session;
  109. }
  110. int sftp_run(ssh_session session, const char* local_file_dir, const char* target_path)
  111. {
  112.     sftp_session sftp;
  113.     // 打开SFTP通道
  114.     sftp = sftp_new(session);
  115.     if (!sftp) {
  116.         fprintf(stderr, "Failed to create SFTP session\n");
  117.         ssh_disconnect(session);
  118.         ssh_free(session);
  119.         return -1;
  120.     }
  121.     if (sftp_init(sftp) != SSH_OK) {
  122.         fprintf(stderr, "Failed to initialize SFTP session\n");
  123.         sftp_free(sftp);
  124.         ssh_disconnect(session);
  125.         ssh_free(session);
  126.         return -1;
  127.     }
  128.     // 得到当前 文件/目录 所在路径
  129.     char local_dir[4096];
  130.     getcwd(local_dir, sizeof(local_dir));
  131.     int len = strlen(local_dir);
  132.     if ((len + strlen(local_file_dir) + 2) >= 4095) {
  133.         perror("Local filename is too long");
  134.         return -1;
  135.     }
  136.     local_dir[len] = '\\';
  137.     local_dir[len + 1] = '\0';
  138.     strcat(local_dir, local_file_dir);
  139.     struct _stat file_stat;
  140.     // 获取文件的详细信息
  141.     if (_stat(local_dir, &file_stat) != 0) {
  142.         perror("stat");
  143.         return -1;
  144.     }
  145.     // 判断文件类型
  146.     //普通文件
  147.     if ((file_stat.st_mode & _S_IFMT) == _S_IFREG) {
  148.         sftp_normal_upload(session, sftp, local_dir, target_path);
  149.     }
  150.     //目录文件
  151.     else if ((file_stat.st_mode & _S_IFMT) == _S_IFDIR) {
  152.         // 递归上传本地目录到远程目录
  153.         if (sftp_recursive_upload(session, sftp, local_dir, target_path) != 1) {
  154.             fprintf(stderr, "Failed to recursively upload directory\n");
  155.             sftp_free(sftp);
  156.             ssh_disconnect(session);
  157.             ssh_free(session);
  158.             return -1;
  159.         }
  160.     }
  161.     else {
  162.         printf("%s 既不是普通文件,也不是目录,无法上传\n", local_dir);
  163.     }
  164.     // 释放
  165.     sftp_free(sftp);
  166.     ssh_disconnect(session);
  167.     ssh_free(session);
  168.     return 1;
  169. }
  170. int ssh_sftp_transmit_password(const char* target_host, const char* target_username,
  171.     const char* target_password, const char* local_file_dir, const char* target_path)
  172. {
  173.     // ssh连接建立
  174.     ssh_session session = ssh_create(target_host, target_username);
  175.     if (session == NULL)return -1;
  176.     // 身份验证 - 密码
  177.     if (ssh_userauth_password(session, NULL, target_password) != SSH_AUTH_SUCCESS) {
  178.         fprintf(stderr, "Failed to authenticate with password\n");
  179.         ssh_disconnect(session);
  180.         ssh_free(session);
  181.         return -1;
  182.     }
  183.     // 传输
  184.     int re = sftp_run(session, local_file_dir, target_path);
  185.     return re;
  186. }
  187. int ssh_sftp_transmit_publickey(const char* target_host, const char* target_username,
  188.     const char* local_file_dir, const char* target_path)
  189. {
  190.     // ssh连接建立
  191.     ssh_session session = ssh_create(target_host, target_username);
  192.     if (session == NULL)return -1;
  193.     // 身份验证 - 密钥
  194.     if (ssh_userauth_publickey_auto(session, NULL, NULL) != SSH_AUTH_SUCCESS) {
  195.         fprintf(stderr, "Authentication failed: %s\n", ssh_get_error(session));
  196.         ssh_disconnect(session);
  197.         ssh_free(session);
  198.         return -1;
  199.     }
  200.     // 传输
  201.     int re = sftp_run(session, local_file_dir, target_path);
  202.     return re;
  203. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

美食家大橙子

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表