使用 Rust 处理 FTP

一、使用 ftp crate

由于我使用的 ftp server 使用了 TLSv1.2 的加密算法,所以必须使用 ftp crate 中的 secure features。故而我们需要为编译做一些准备工作,否则会编译失败。

1、准备工作

ftp cratebuild.rs 中可以发现其依赖 openssl 的版本是 1.0.1 / 1.0.2 / 1.1.0 这三个版本中的任意一个。

    match env::var("DEP_OPENSSL_VERSION") {
        Ok(ref v) if v == "101" => {
            println!("cargo:rustc-cfg=ossl101");
            println!("cargo:rustc-cfg=ossl10x");
        }
        Ok(ref v) if v == "102" => {
            println!("cargo:rustc-cfg=ossl102");
            println!("cargo:rustc-cfg=ossl10x");
        }
        Ok(ref v) if v == "110" => {
            println!("cargo:rustc-cfg=ossl110");
        }
        _ => panic!("Unable to detect OpenSSL version"),
    }

所以我们需要先编译好这三个版本中的一个,我编译的是 1.1.0l :

  • 从 openssl 网站的 source/old 选择下载 openssl-1.1.0l 代码;并将压缩包解压;
  • 下载安装 perl ,我用的是 5.32 版本;安装完执行 perl -v 查看版本,确定安装成功;
  • 下载 nasm ,我用的是 nasm-2.16.01-win64 ;将其解压,并把两个 exe 文件拷贝到代码解压目录;
  • 然后运行 perl configure VC-WIN64A --prefix=D:\OpenSSL\x64 ,这样配置最终会安装到 D:\tools\OpenSSL 目录下;
  • 再执行 nmake ,等待执行编译结束;
  • 最后用管理员权限运行 cmd,并在代码目录下执行 nmake install ;这一步就会将编译产物拷贝到 D:\tools\OpenSSL 目录下。
  • 再添加几个环境变量:
OPENSSL_DIR=D:\tools\OpenSSL
OPENSSL_INCLUDE_DIR=D:\tools\OpenSSL\include
OPENSSL_LIB_DIR=D:\tools\OpenSSL\lib

2、代码编译

首先添加 ftp crate 依赖,需要使用 secure features:

[dependencies]
ftp = { version = "3.0.1", features = ["secure"] }

示例代码:

use ftp::FtpStream;
use ftp::openssl::ssl::{ SslContext, SslMethod };

fn main() {
    let ftp_stream = FtpStream::connect("127.0.0.1:21").unwrap();
    let ctx = SslContext::builder(SslMethod::tls()).unwrap().build();
    let mut ftp_stream = ftp_stream.into_secure(ctx).unwrap();
    ftp_stream.login("username", "password").unwrap();
    println!("{}", ftp_stream.pwd().unwrap());  //列出当前目录
    let _ = ftp_stream.quit();
}

编译执行:

D:\Codes\rust\study>cargo run
   Compiling study v0.1.0 (D:\Codes\rust\study)
    Finished dev [unoptimized + debuginfo] target(s) in 0.56s
warning: the following packages contain code that will be rejected by a future version of Rust: winapi v0.2.8
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 12`
     Running `target\debug\study.exe`
/               #刚登陆在根目录

D:\Codes\rust\study>

追加 Note: ftp crate 不支持 openssl 1.1.0 以上的版本,且依赖 winapi crate 版本较低,将被丢弃。所以建议使用 suppaftp crate 而不是 ftp crate

二、使用 suppaftp crate

这个没啥好说的,直接上代码:

[dependencies]
suppaftp = "^4.7.0"

如果使用了 SSL/TLS 加密了,则需要启用 native-tls 或者 rustls ,例如 native-tls :

[dependencies]
suppaftp = { version = "^4.7.0", features = ["native-tls"] }

代码示例:

use suppaftp::FtpStream;
use suppaftp::native_tls::TlsConnector;

fn main() {
    let ftp = FtpStream::connect("127.0.0.1:21").expect("connect error");
    let mut ftp = ftp.into_secure(TlsConnector::new().expect("Tls connetor new error").into(), "127.0.0.1").expect("into secure error");
    ftp.login("username", "password").expect("login error");

    ftp.set_mode(suppaftp::types::Mode::ExtendedPassive);
    ftp.cwd("/wlb").expect("cwd error");
    println!("{}", ftp.pwd().expect("pwd error"));
    let list_dir  = ftp.nlst(Some("/wlb")).expect("nlst error");
    println!("{:#?}", list_dir);

    ftp.quit().unwrap();
}

有一个需要注意的点,连接时有三种模式:

pub enum Mode {
    Active,
    ExtendedPassive,
    Passive,
}

登录上去默认是 Passive 模式,在这个模式下无法使用 nlst() 等方法。需要将其设置为 ExtendedPassive 模式。即

ftp.set_mode(suppaftp::types::Mode::ExtendedPassive);

以上代码执行结果如下:

PS D:\Codes\rust\suppaftp> cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.06s
     Running `target\debug\suppaftp.exe`
/wlb
[
    "/wlb/aaaa",
    "/wlb/bbbbbbbb",
    "/wlb/cccccccccc",
    "/wlb/2023-02-22-18-16-34_2.7z",
    "/wlb/2023-02-23-10-22-45_2.7z",
]
Hello, world!
PS D:\Codes\rust\suppaftp>

其他信息可以在 docs.rs 上查看 FtpStream in suppaftp - Rust (docs.rs)

你可能感兴趣的:(笔记,rust,ftp)