You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Hyper中接收POST请求的表单及文件数据?

在Hyper中接收POST请求的表单数据(含文件上传)

场景说明

需要处理的POST请求(通过curl发送):

curl -X POST -F "field=@/path/to/file.txt" -F "tool=curl" -F "other-file=@/path/to/other.jpg" http://localhost:8000

现有Hyper基础代码:

use std::{convert::Infallible, net::SocketAddr};
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};

async fn handle(_: Request<Body>) -> Result<Response<Body>, Infallible> {
    Ok(Response::new("Hello, World!".into()))
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 8000));

    let make_svc = make_service_fn(|_conn| async {
        Ok::<_, Infallible>(service_fn(handle))
    });

    let server = Server::bind(&addr).serve(make_svc);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

遇到的问题

尝试用multipart crate处理请求时,编写了如下代码:

async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    let mut files = multipart::server::Multipart::from(req);
     .....
}

出现错误:

expected struct multipart::server::Multipart, found struct hyper::Request


解决方案

1. 添加正确的依赖

原multipart crate不直接兼容Hyper的Request类型,需要使用multipart-rfc7578(专门适配Hyper等异步HTTP库的multipart处理库),同时保留hyper和tokio依赖。在Cargo.toml中添加:

[dependencies]
hyper = { version = "1.1", features = ["full"] }
tokio = { version = "1.0", features = ["full"] }
multipart-rfc7578 = "0.6"
bytes = "1.0"

2. 修改请求处理逻辑

核心步骤:

  • 判断请求方法是否为POST
  • 检查Content-Type是否为multipart/form-data
  • 从请求中提取multipart流,逐个解析字段和文件

修改后的完整代码:

use std::{convert::Infallible, net::SocketAddr};
use hyper::{Body, Request, Response, Server, StatusCode};
use hyper::service::{make_service_fn, service_fn};
use multipart_rfc7578::server::{Multipart, Field};
use bytes::Bytes;

async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
    // 仅处理POST请求
    if req.method() != hyper::Method::POST {
        return Ok(Response::builder()
            .status(StatusCode::METHOD_NOT_ALLOWED)
            .body("Only POST is allowed".into())
            .unwrap());
    }

    // 解析multipart请求
    match Multipart::try_from(req).await {
        Ok(mut multipart) => {
            let mut result = String::new();
            // 遍历所有字段
            while let Some(field) = multipart.next_field().await.unwrap() {
                match field {
                    Field::Text(name, value) => {
                        // 处理文本字段
                        let text = String::from_utf8(value.into_bytes().to_vec()).unwrap();
                        result.push_str(&format!("Text field '{}': {}\n", name, text));
                    }
                    Field::File(name, file) => {
                        // 处理文件字段
                        let filename = file.file_name().unwrap_or("unknown").to_string();
                        // 读取文件内容(示例转为Bytes,可按需写入磁盘)
                        let content = file.into_bytes().await.unwrap();
                        result.push_str(&format!("File field '{}' ({}): {} bytes\n", name, filename, content.len()));
                    }
                }
            }
            Ok(Response::new(result.into()))
        }
        Err(e) => {
            // 处理解析错误
            Ok(Response::builder()
                .status(StatusCode::BAD_REQUEST)
                .body(format!("Multipart parse error: {}", e).into())
                .unwrap())
        }
    }
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 8000));

    let make_svc = make_service_fn(|_conn| async {
        Ok::<_, Infallible>(service_fn(handle))
    });

    let server = Server::bind(&addr).serve(make_svc);

    if let Err(e) = server.await {
        eprintln!("server error: {}", e);
    }
}

3. 错误原因解释

你之前的错误是因为multipart::server::Multipart仅支持该 crate 自身定义的请求类型,无法直接接收Hyper的Request<Body>。multipart-rfc7578库做了专门适配,提供Multipart::try_from(req)方法,可直接从Hyper请求对象创建解析器,解决了类型不兼容的问题。


内容的提问来源于stack exchange,提问作者DFG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 08:55:17