Rust笔记:06-Rust使用reqwest发送上传 multipart form file

Rust笔记:06-Rust使用reqwest发送上传 multipart form file

1.背景

1.1 RUST Reqwest

Reqwest 是一个简单而强大的 RUST HTTP 客户端,用于浏览器异步 HTTP 请求。支持 xmlHttpRequest, JSONP, CORS, 和 CommonJS 约束,特点:

  • 一个符合人体工程学,基于 Rust 的 HTTP 客户端。
  • Plain bodies, JSON, urlencoded, multipart
  • Customizable redirect policy
  • HTTP Proxies
  • HTTPS via system-native TLS (or optionally, rustls)
  • Cookie Store
  • Multipart Form 表单文件上传
  • WASM

1.2 rust json struct 转换工单

QuickType 是一款可以根据 json 文本生成指定语言(如 Type Script,C++,,Java,Rust,Go 等)类型声明代码的工具.

例如我们在写接口调用处理收到响应数据的逻辑时一般分为如下两步:

1.根据接口返回的 JSON 格式写一个对应的类型 2.写 JSON 格式验证与解析逻辑来根据收到的数据生成对应的类对象

使用 QuickType 工具就可以根据 JSON 文本帮助我们自动生成以上两部分的代码.

https://app.quicktype.io/

2.cargo.toml

[package]
name = "orderhunter"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
axum = "0.5.10"
hyper = { version = "0.14.19", features = ["full"] }
tower = "0.4.13"
tokio = { version = "1.19", features = ["macros", "rt-multi-thread"] }
clap = { version = "3.2", features = ["derive","env"] }
anyhow = "1.0.58"
dotenv = "0.15.0"
env_logger = "0.9.0"
sqlx = { version = "0.6", features = ["mysql","runtime-tokio-native-tls",  "uuid", "time"] }
tower-http = { version = "0.2.0", features = ["trace"] }
serde = { version = "1.0.137", features = ["derive","std"] }
serde_json = "1.0.82"
multipart = { version = "0.18.0", features = ["hyper"] }
reqwest = { version = "0.11.11", features = ["stream","multipart","json"] }
futures = "0.3.21"
tokio-util = { version = "0.7.3", features = ["codec"] }

3. Reqwest 上传 Multipart Form 表单文件

use tokio::fs::File;
use tokio_util::codec::{BytesCodec, FramedRead};
use reqwest::{Body, Client,multipart};
use super::httpclient::HttpBinResult;

async fn reqwest_multipart_form(url:&str) -> anyhow::Result<HttpBinResult> {
    let client = Client::new();

    //路径和 cargo.toml 在一个目录下面
    let file = File::open(".gitignore").await?;
    let file_body = file_to_body(file);

    let bio = multipart::Part::stream(file_body)
    .file_name("gitignore.txt")
    .mime_str("text/plain")?;

    let form = multipart::Form::new()
    .text("username", "seanmonstar")
    .text("password", "secret")
    .part("file", bio);

    let response = client.post(url).multipart(form).send().await?;
    // let print_string = response.text().await?;
    // println!("{:?}",print_string   );
    let result = response.json::<HttpBinResult>().await?;
    // let result = HttpBinResult { args: None, data:None, files:None, form:None, headers: None, json: None, origin: None, url: None };
    Ok(result)
}


fn file_to_body(file: File) -> Body {
    let stream = FramedRead::new(file, BytesCodec::new());
    let body = Body::wrap_stream(stream);
    body
}

#[cfg(test)]
mod tests {
    // 注意这个惯用法:在 tests 模块中,从外部作用域导入所有名字。
    use super::*;

    #[tokio::test]
    async fn test_post_form_file() {
        let url = "http://httpbin.org/post?a=1&b=true";
        let get_json = reqwest_multipart_form(url).await.unwrap();
        // print users
        println!("users: {:#?}", get_json);
    }

}

The End

线上交流工具: 在你的terminal中输入 ssh $用户@mojotv.cn

在你的terminal中输入 ssh mojotv.cn hn 查看最新 hacknews

目录