Send file in chunks using tokio

#1

Hello,

I am trying to send a file over the network. In case the file is too big, I use a BufferedReader, turn it into bytes, and then use the itertools chunks method to read the file chunk by chunk.

I would like to write the file to a TcpStream using tokio. But I can’t exactly figure out how to do this. I normally would use the write_all method to write to a socket, but this consumes the writer. So if I understand correctly I need to somehow chain some futures so that each one passes the writer to the next one. But as I understand, because the type of the future contains all previous futures, the number of futures I create must be known at compile time.

I tried playing with streams, but then I don’t see how I can pass the writer to each future.

#2

You can turn the file into a stream and turn the socket into a sink, then use forward() to send all the data:

use tokio::codec::{BytesCodec, Decoder};
use tokio::fs::File;
use tokio::net::TcpStream;
use tokio::prelude::*;

fn send_file(file: File, socket: TcpStream) -> impl Future<Item = (), Error = std::io::Error> {
    BytesCodec::new()
        .framed(file)
        .map(Into::into)
        .forward(BytesCodec::new().framed(socket))
        .map(|_| ())
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ad066c40109dbd0635efed1e8c412792

1 Like