When using streaming methods like put_with_stream, append_with_stream, or retr_as_stream, the returned TransferStream must be explicitly finalized to ensure the transfer was successful.
Calling .finish() closes the data socket and reads the server's completion reply (e.g., 226 or 250) on the control connection. This is the only reliable way to confirm the transfer succeeded. If you do not call .finish(), the stream will attempt to finalize on Drop, but this is a best-effort operation that logs errors instead of returning them, and the transfer outcome may be lost.
Important:
- You must call
.finish() before issuing any other command on the FTP client. - If using buffered writers, ensure you
flush() them before calling .finish(). - While a
TransferStream is alive, the client will return FtpError::DataConnectionAlreadyOpen if you attempt to open another data connection.
use std::io::Write;
use suppaftp::FtpStream;
let mut ftp = FtpStream::connect("127.0.0.1:21").unwrap();
ftp.login("test", "test").unwrap();
// Start an upload stream
let mut upload = ftp.put_with_stream("hello.txt").unwrap();
// Write data to the stream
upload.write_all(b"hello, world!").unwrap();
// CRITICAL: Finalize the transfer to read the server's completion reply
// and make the control connection ready for the next command.
upload.finish().unwrap();
assert_eq!(ftp.size("hello.txt").unwrap(), 13);