7

reqwest v0.9.18的文档显示了以下发布文件的示例:

let file = fs::File::open("from_a_file.txt")?;
let client = reqwest::Client::new();
let res = client.post("http://httpbin.org/post")
    .body(file)
    .send()?;

reqwest v0.11的最新文档不再包含此示例,并且在调用时尝试构建它失败并出现以下错误body()

the trait `From<std::fs::File>` is not implemented for `Body`

发送文件的更新方法是什么?

4

1 回答 1

12

您链接到的具体示例在使用 async的reqwestcrate之前。如果你想使用那个确切的例子,那么reqwest::Client你需要使用. 而不是reqwest::blocking::Client. 这也需要启用该blocking功能。

需要明确的是,您实际上仍然可以找到该示例,它只是位于reqwest::blocking::RequestBuilder'sbody()方法的文档中。

// reqwest = { version = "0.11", features = ["blocking"] }
use reqwest::blocking::Client;
use std::fs::File;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let file = File::open("from_a_file.txt")?;

    let client = Client::new();
    let res = client.post("http://httpbin.org/post")
        .body(file)
        .send()?;

    Ok(())
}

还要检查reqwest'sFormRequestBuilder'multipart()方法,例如有一个file()方法。


如果您确实想使用异步,那么您可以使用FramedReadfrom the tokio-utilcrate。连同TryStreamExt特质,来自futurescrate

只需确保启用 的stream功能reqwest和 的codec功能tokio-util

// futures = "0.3"
use futures::stream::TryStreamExt;

// reqwest = { version = "0.11", features = ["stream"] }
use reqwest::{Body, Client};

// tokio = { version = "1.0", features = ["full"] }
use tokio::fs::File;

// tokio-util = { version = "0.6", features = ["codec"] }
use tokio_util::codec::{BytesCodec, FramedRead};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let file = File::open("from_a_file.txt").await?;

    let client = reqwest::Client::new();
    let res = client
        .post("http://httpbin.org/post")
        .body(file_to_body(file))
        .send()
        .await?;

    Ok(())
}

fn file_to_body(file: File) -> Body {
    let stream = FramedRead::new(file, BytesCodec::new());
    let body = Body::wrap_stream(stream);
    body
}
于 2021-01-20T18:35:57.493 回答