是否有某种类型可以从实现 Stream 的 File 构造?
不,不幸的是。没有内置任何东西std
, futures
or tokio
目前可以直接执行此操作。
由于 Stream 项目的“分离”性质,这样的实现必须为每个传入数据片分配一个新的拥有的缓冲区并将其移交给调用者。那效率不会很高。直到 Rust 语言拥有泛型关联类型 (GAT)(希望在明年),我们才能满意地解决这个问题。查看this futures-rs ticket https://github.com/rust-lang/futures-rs/issues/2006 and Niko 的异步采访 #2 https://smallcultfollowing.com/babysteps/blog/2019/12/10/async-interview-2-cramertj-part-2/了解更多详情。
话虽这么说,现在有一些用例Stream
底层 IO 之上的门面是理想的并且足够好。
制作我自己的元组结构(包装 File 并实现 Stream 本身)的正确解决方案是正确的解决方案吗?这个实现很简单吗?
For futures-0.1
认为rusoto
取决于,有几种方法可以实现这一点:
- 实施
Stream
包装 a 的结构体的特征Read
- 利用
futures
效用函数,例如futures::stream::poll_fn
-
tokio-codec-0.1
具有优秀的FramedRead
已经实施的Stream
第三个肯定是最简单的:
use futures::stream::Stream; // futures = "0.1.29"
use rusoto_core::{ByteStream, Region}; // rusoto_core = "0.42.0"
use rusoto_s3::{PutObjectOutput, PutObjectRequest, S3Client, S3}; // rusoto_s3 = "0.42.0"
use std::{error::Error, fs::File, path::Path};
use tokio_codec::{BytesCodec, FramedRead}; // tokio-codec = "0.1.1"
use tokio_io::io::AllowStdIo; // tokio-io = "0.1.12"
fn upload_file(file_path: &Path) -> Result<PutObjectOutput, Box<dyn Error>> {
let file = File::open(file_path)?;
let aio = AllowStdIo::new(file);
let stream = FramedRead::new(aio, BytesCodec::new()).map(|bs| bs.freeze());
let client = S3Client::new(Region::UsEast1);
let mut request = PutObjectRequest::default();
request.body = Some(ByteStream::new(stream));
Ok(client.put_object(request).sync()?)
}