gpt4 book ai didi

rust-tokio - 如何将超响应正文写入文件?

转载 作者:行者123 更新时间:2023-12-03 14:42:39 30 4
gpt4 key购买 nike

我正在尝试使用 tokio 编写一个测试程序,该程序从网站获取文件并将流式响应写入文件。 hyper 网站显示了一个使用 while 循环并使用 .data() 的示例。方法响应主体,但我想用 .map() 操作流和其他几个。

我认为下一个合理的尝试是将流转换为 AsyncRead通过使用 .into_async_read()方法来自 TryStreamExt ,但这似乎不起作用。我不得不使用 map 来转换 hyper::error::Errorstd::error::Error获得 TryStream ,但现在编译器告诉我 AsyncRead没有为转换后的流实现。这是我的 main.rs 文件和错误:

src/main.rs

use futures::stream::{StreamExt, TryStreamExt};
use http::Request;
use hyper::{Body, Client};
use hyper_tls::HttpsConnector;
use tokio::fs::File;
use tokio::io;

use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let https = HttpsConnector::new();
let client = Client::builder().build::<_, Body>(https);

let request = Request::get("some file from the internet").body(Body::empty())?;
let response = client.request(request).await?;

let mut stream = response
.body()
.map(|result| result.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, "Error!")))
.into_async_read();
let mut file = File::create("output file").await?;

io::copy(&mut stream, &mut file).await?;

Ok(())
}

错误
error[E0277]: the trait bound `futures_util::stream::try_stream::into_async_read::IntoAsyncRead<futures_util::stream::stream::map::Map<hyper::body::body::Body, [closure@src/main.rs:20:14: 20:103]>>: tokio::io::async_read::AsyncRead` is not satisfied
--> src/main.rs:24:5
|
24 | io::copy(&mut stream, &mut file).await?;
| ^^^^^^^^ the trait `tokio::io::async_read::AsyncRead` is not implemented for `futures_util::stream::try_stream::into_async_read::IntoAsyncRead<futures_util::stream::stream::map::Map<hyper::body::body::Body, [closure@src/main.rs:20:14: 20:103]>>`
|
::: /Users/jackson/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-0.2.13/src/io/util/copy.rs:63:12
|
63 | R: AsyncRead + Unpin + ?Sized,
| --------- required by this bound in `tokio::io::util::copy::copy`

error[E0277]: the trait bound `futures_util::stream::try_stream::into_async_read::IntoAsyncRead<futures_util::stream::stream::map::Map<hyper::body::body::Body, [closure@src/main.rs:20:14: 20:103]>>: tokio::io::async_read::AsyncRead` is not satisfied
--> src/main.rs:24:5
|
24 | io::copy(&mut stream, &mut file).await?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `tokio::io::async_read::AsyncRead` is not implemented for `futures_util::stream::try_stream::into_async_read::IntoAsyncRead<futures_util::stream::stream::map::Map<hyper::body::body::Body, [closure@src/main.rs:20:14: 20:103]>>`
|
= note: required because of the requirements on the impl of `core::future::future::Future` for `tokio::io::util::copy::Copy<'_, futures_util::stream::try_stream::into_async_read::IntoAsyncRead<futures_util::stream::stream::map::Map<hyper::body::body::Body, [closure@src/main.rs:20:14: 20:103]>>, tokio::fs::file::File>`

最佳答案

你几乎拥有它。您调用了 into_async_read这为您提供了 futures::io::AsyncRead 的实现但你想要一个 tokio::io::AsyncRead .
tokio-util crate 为您提供了进行此转换的工具。
添加到您的 Cargo.toml :

tokio-util = { version = "0.3.1", features=["compat"] }
假设你添加了一个这样的转换函数:
fn to_tokio_async_read(r: impl futures::io::AsyncRead) -> impl tokio::io::AsyncRead {
tokio_util::compat::FuturesAsyncReadCompatExt::compat(r)
}
那么你的代码可能会变成:
let mut futures_io_async_read = response
.body()
.map(|result| result.map_err(|error| std::io::Error::new(std::io::ErrorKind::Other, "Error!")))
.into_async_read();

let tokio_async_read = to_tokio_async_read(futures_io_async_read)

let mut file = File::create("output file").await?;

io::copy(&mut tokio_async_read, &mut file).await?;

关于rust-tokio - 如何将超响应正文写入文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60964238/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com