如何使用 libssh 和 SFTP 在 C/C++ 中复制文件

Posted

技术标签:

【中文标题】如何使用 libssh 和 SFTP 在 C/C++ 中复制文件【英文标题】:How to copy a file in C/C++ with libssh and SFTP 【发布时间】:2012-11-21 09:46:00 【问题描述】:

我想将文件从客户端复制到远程服务器,但我不明白如何使用 libssh 库 SFTP API 来完成。

情况是:SSH会话打开了,SFTP会话也打开了,我可以用libssh的集成功能创建一个文件从客户端写入到服务器。

我没有找到一种简单的方法来使用简单的函数将文件从客户端复制到服务器 sftp_transfer(sourceFile(like c:\my document\hello world.txt),RemoteFile(/home/ user/hello world.txt),right(读写)) ?

根据我从教程中了解到的,它首先在远程位置(服务器)创建一个文件,然后用这行代码打开这个文件:

file = sftp_open(sftp, "/home/helloworld.txt",access_type,1);

在服务器上创建文件之后,它正在使用缓冲区写入这个创建的文件:

const char *helloworld = "Hello, World!\n";
int length = strlen(helloworld);
nwritten = sftp_write(file, helloworld, length);

我现在的问题是,如果我有一个文件,例如一个 .doc 文件,并且我想将该文件从 c:\mydocument\document.doc 传输/上传到远程服务器 /home/user/document.doc,我该如何使用这种方法呢?

如何将此文件放入sftp_write() 函数中以像helloworld in the sample function 一样发送?

我可能在编程方面不够好,无法理解,但我真的很努力去理解它并且我坚持下去。

提前感谢您的帮助

下面是我用来测试的代码示例:

// Set variable for the communication
char buffer[256];
unsigned int nbytes;

//create a file to send by SFTP
int access_type = O_WRONLY | O_CREAT | O_TRUNC;
const char *helloworld = "Hello, World!\n";
int length = strlen(helloworld);

//Open a SFTP session
sftp = sftp_new(my_ssh_session);
if (sftp == NULL)

    fprintf(stderr, "Error allocating SFTP session: %s\n",
    ssh_get_error(my_ssh_session));
    return SSH_ERROR;

// Initialize the SFTP session
rc = sftp_init(sftp);
if (rc != SSH_OK)

    fprintf(stderr, "Error initializing SFTP session: %s.\n",
    sftp_get_error(sftp));
    sftp_free(sftp);
    return rc;


//Open the file into the remote side
file = sftp_open(sftp, "/home/helloworld.txt",access_type,1);
if (file == NULL)

    fprintf(stderr, "Can't open file for writing: %s\n",ssh_get_error(my_ssh_session));
    return SSH_ERROR;


//Write the file created with what's into the buffer
nwritten = sftp_write(file, helloworld, length);
if (nwritten != length)

    fprintf(stderr, "Can't write data to file: %s\n",
    ssh_get_error(my_ssh_session));
    sftp_close(file);
    return SSH_ERROR;

【问题讨论】:

【参考方案1】:

以通常的方式打开文件(使用 C++ 的 fstream 或 C 的 stdio.h),将其内容读取到缓冲区,然后将缓冲区传递给 sftp_write

类似这样的:

ifstream fin("file.doc", ios::binary);
if (fin) 
  fin.seekg(0, ios::end);
  ios::pos_type bufsize = fin.tellg();   // get file size in bytes
  fin.seekg(0);                          // rewind to beginning of file

  std::vector<char> buf(bufsize);        // allocate buffer
  fin.read(buf.data(), bufsize);         // read file contents into buffer

  sftp_write(file, buf.data(), bufsize); // write buffer to remote file

请注意,这是一个非常简单的实现。您可能应该以附加模式打开远程文件,然后将数据分块写入,而不是发送单个巨大的数据块。

【讨论】:

【参考方案2】:

以下示例在循环中使用ifstream 以避免将整个文件加载到内存中(正如接受的答案那样):

ifstream fin("C:\\myfile.zip", ios::binary);

while (fin)

    constexpr size_t max_xfer_buf_size = 10240
    char buffer[max_xfer_buf_size];
    fin.read(buffer, sizeof(buffer));
    if (fin.gcount() > 0)
    
        ssize_t nwritten = sftp_write(NULL, buffer, fin.gcount());
        if (nwritten != fin.gcount())
        
            fprintf(stderr, "Error writing to file: %s\n", ssh_get_error(ssh_session));
            sftp_close(file);
            return 1;
        
    

【讨论】:

【参考方案3】:

我用了here的例子。

sftp_read_sync 使用无限循环将文件从服务器读取到/path/to/profile 来自服务器路径/etc/profile

【讨论】:

以上是关于如何使用 libssh 和 SFTP 在 C/C++ 中复制文件的主要内容,如果未能解决你的问题,请参考以下文章

ssh能够连接而sftp不能连接的解决方法 无标题文章

centos sftp安装

SFTP远程连接服务器上传下载文件-vs2010项目实例

用于端口转发的 libssh2 示例代码

使用 make install 安装 libssh 构建时出错

使用libssh链接期间未定义的符号