You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Rust实现SFTP文件上传?现有方案遇问题求助

Rust实现SFTP文件上传问题

需求

  • 用Rust代码实现向SFTP服务器上传文件
  • 找到openssh-sftp-client crate,但因文档匮乏无法上手
  • 禁止使用sftp/rftp等命令行工具

已尝试的Crate及问题

1. ssh2 crate

代码示例:

use std::io::prelude::*;
use std::net::TcpStream;
use std::path::Path;
use ssh2::Session;

// 连接SSH服务器
let tcp = TcpStream::connect("SFTP_IP:PORT").unwrap();
let mut sess = Session::new().unwrap();
sess.set_tcp_stream(tcp);
sess.handshake().unwrap();
sess.userauth_agent("username").unwrap();

// 写入文件
let mut remote_file = sess.scp_send(Path::new("remote"),
                                    0o644, 10, None).unwrap();
remote_file.write(b"1234567890").unwrap();
// 关闭通道并等待传输完成
remote_file.send_eof().unwrap();
remote_file.wait_eof().unwrap();
remote_file.close().unwrap();
remote_file.wait_close().unwrap();

错误:认证失败。问题出在使用userauth_agent认证方式,若服务器不支持agent认证或本地无可用agent,就会触发该错误;同时这段代码用的是SCP协议而非SFTP,不符合需求。

2. rust-ftp crate

代码示例:

use std::str;
use std::io::Cursor;
use ftp::FtpStream;

fn main() {
    // 连接FTP服务器并认证
    let mut ftp_stream = FtpStream::connect("SFTP_IP:PORT").unwrap();
    let _ = ftp_stream.login("username", "password").unwrap();

    // 获取当前目录
    println!("Current directory: {}", ftp_stream.pwd().unwrap());

    // 切换目录
    let _ = ftp_stream.cwd("test_data").unwrap();

    // 下载文件
    let remote_file = ftp_stream.simple_retr("ftpext-charter.txt").unwrap();
    println!("Read file with contents
{}
", str::from_utf8(&remote_file.into_inner()).unwrap());

    // 上传文件
    let mut reader = Cursor::new("Hello from the Rust \"ftp\" crate!".as_bytes());
    let _ = ftp_stream.put("greeting.txt", &mut reader);
    println!("Successfully wrote greeting.txt");

    // 断开连接
    let _ = ftp_stream.quit();
}

错误:无法连接服务器。原因是rust-ftp是专门用于FTP协议的库,而SFTP是基于SSH的完全不同的协议,两者不兼容,因此无法通过该库连接SFTP服务器。

可行解决方案

方案1:使用ssh2 crate实现SFTP

ssh2原生支持SFTP协议,修正后的代码如下:

use std::io::prelude::*;
use std::net::TcpStream;
use ssh2::Session;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 连接SSH服务器(SFTP默认端口为22)
    let tcp = TcpStream::connect("SFTP_IP:22")?;
    let mut sess = Session::new()?;
    sess.set_tcp_stream(tcp);
    sess.handshake()?;

    // 替换为你的用户名和密码,或改用密钥认证
    sess.userauth_password("your_username", "your_password")?;

    // 确认认证成功
    assert!(sess.authenticated());

    // 初始化SFTP会话
    let sftp = sess.sftp()?;

    // 创建并写入远程文件
    let mut remote_file = sftp.create("/remote/path/your_file.txt")?;
    remote_file.write_all(b"Content to upload")?;
    remote_file.close()?;

    println!("文件上传成功");
    Ok(())
}

方案2:使用openssh-sftp-client crate

该库基于OpenSSH实现异步SFTP操作,示例代码如下:

use openssh_sftp_client::SftpClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 建立SSH连接:格式为 "用户名@服务器地址:端口"
    let client = SftpClient::connect("your_username@SFTP_IP:22", None).await?;

    // 上传本地文件到远程路径
    client.upload("/local/path/your_file.txt", "/remote/path/your_file.txt").await?;

    println!("文件上传成功");
    Ok(())
}

注意事项:

  • 需要在Cargo.toml中添加依赖:openssh-sftp-client = "0.1.5"(版本号请以最新为准)
  • 若使用密钥认证,可将第二个参数改为私钥路径,例如Some("/home/user/.ssh/id_rsa")

内容的提问来源于stack exchange,提问作者Hamza Zubair

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:35:23