【问题标题】:How to write a hyper response body to a file?如何将超响应正文写入文件?
【发布时间】:2020-07-12 19:27:02
【问题描述】:

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

我认为下一个合理的尝试是使用来自TryStreamExt.into_async_read() 方法将流转换为AsyncRead,但这似乎不起作用。我必须使用映射将hyper::error::Error 转换为std::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>`

【问题讨论】:

    标签: rust-tokio hyper


    【解决方案1】:

    你几乎拥有它。您调用了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?;
    

    【讨论】:

    • add tokio-util = { version = "0.3.1", features=["compat"] } 会起作用的,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    相关资源
    最近更新 更多