rust 使用Axum和时雄下载文件时可以使用什么签名?

thtygnil  于 2022-12-13  发布在  其他
关注(0)|答案(1)|浏览(240)

我使用axum和这个代码(在这里找到)下载文件:

use axum::{
    body::StreamBody,
    http::{header, StatusCode},
    response::{Headers, IntoResponse},
    routing::get,
    Router,
};
use std::net::SocketAddr;
use tokio_util::io::ReaderStream;

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(handler));

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

async fn handler() -> impl IntoResponse {
    // `File` implements `AsyncRead`
    let file = match tokio::fs::File::open("Cargo.toml").await {
        Ok(file) => file,
        Err(err) => return Err((StatusCode::NOT_FOUND, format!("File not found: {}", err))),
    };

    // convert the `AsyncRead` into a `Stream`
    let stream = ReaderStream::new(file);

    // convert the `Stream` into an `axum::body::HttpBody`
    let body = StreamBody::new(stream);

    let headers = Headers([
        (header::CONTENT_TYPE, "text/toml; charset=utf-8"),
    ]);

    Ok((headers, body))
}

一切正常。但是我找不到一种方法来将下面的代码移到一个单独的函数中:

let file = match tokio::fs::File::open("Cargo.toml").await {
    Ok(file) => file,
    Err(err) => return Err((StatusCode::NOT_FOUND, format!("File not found: {}", err))),
};

我希望在此函数中同时使用tokio::fs::Filehttps://crates.io/crates/rust-s3方法。

因此,我需要一个“公共类型”,我认为它应该是AsyncRead
函数的签名应该是什么?
我试探着:

use tokio::io::AsyncRead;

pub struct Player {
    db: Arc<DB>
}

impl Handler {
    pub async fn player_pdf(
        &self,
        id: &str,
    ) -> Result<&(dyn AsyncRead)> {
        //...use id here...

        let file = &tokio::fs::File::open("player.pdf").await?;

        Ok(file)
    }
}

但我得到了错误:

error[E0308]: mismatched types
    |
55  |         Ok(file)
    |         -- ^^^^
    |         |  |
    |         |  expected reference, found struct `tokio::fs::File`
    |         |  help: consider borrowing here: `&file`
    |         arguments to this enum variant are incorrect
    |
    = note: expected reference `&dyn tokio::io::AsyncRead`
                  found struct `tokio::fs::File`

我试探着:let file = &tokio::fs::File::open("player.pdf").await?;,得到:

error[E0515]: cannot return value referencing temporary value
   |
43 |         let file = &tokio::fs::File::open(...
   |                     --------------------------- temporary value created here
...
55 |         Ok(file)
   |         ^^^^^^^^ returns a value referencing data owned by the current function

我能用什么?

5ktev3wc

5ktev3wc1#

返回一个通用的“boxed”值可能是这里的解决方案:

impl Handler {
    pub async fn player_pdf(
        &self,
        id: &str,
    ) -> Result<Box<dyn AsyncRead>> {
        //...use id here...

        Ok(Box::new(tokio::fs::File::open("player.pdf").await?))
    }
}

现在没有悬空引用,它被封装并完全拥有。

相关问题