Actix 官方没有描述如何上传文件, 以下是参考网友的资料整理的。
为了简洁, 将环境配置相关信息放到文章最后了。

上传一个文件

这段代码是改写actix-multipart页面的示例的。

use std::io::Read;
use actix_web::{post, App, HttpServer, Responder};
use actix_multipart::form::{tempfile::TempFile, MultipartForm};

#[derive(Debug, MultipartForm)]
struct UploadForm {
    #[multipart(limit = "100MB")]
    file: TempFile,
}

#[post("/upload")]
pub async fn upload(MultipartForm(mut form): MultipartForm<UploadForm>) -> impl Responder {
    // 获得文件 Bytes
    let mut buffer = vec![];
    let _ = form.file.file.read_to_end(&mut buffer);
    format!(
        "Uploaded file {:?}, with size: {}",
        form.file.file_name, form.file.size
    )
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || App::new().service(upload))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

请求

require "uri"
require "net/http"
url = URI("http://127.0.0.1:8080/upload")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
form_data = [['file', File.open("/file/path")]]
request.set_form form_data, 'multipart/form-data'
response = http.request(request)
puts response.read_body

上传文件并且添加描述信息

use actix_multipart::form::{tempfile::TempFile, text::Text, MultipartForm};
use actix_web::{post, App, HttpServer, Responder};

#[derive(Debug, MultipartForm)]
struct UploadForm {
    #[multipart(limit = "100MB")]
    file: TempFile,
    desc: Text<String>,
}

#[post("/upload")]
pub async fn upload(MultipartForm(form): MultipartForm<UploadForm>) -> impl Responder {
    format!(
        "Uploaded file {:?}, with size: {}, description: {:?}",
        form.file.file_name, form.file.size, form.desc
    )
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || App::new().service(upload))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

请求

require "uri"
require "net/http"

url = URI("http://127.0.0.1:8080/upload")

http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
form_data = [['file', File.open('/file/path')],['desc', "example"]]
request.set_form form_data, 'multipart/form-data'
response = http.request(request)
puts response.read_body

上传多个文件(一个参数里传输多个文件)

这个笔者没有找到相关资料, 是笔者自己试出来的代码。

use actix_multipart::form::{tempfile::TempFile, MultipartForm};
use actix_web::{post, App, HttpServer, Responder};

#[derive(Debug, MultipartForm)]
struct UploadForm {
    #[multipart(limit = "100MB")]
    file: Vec<TempFile>,
}

#[post("/upload")]
pub async fn upload(MultipartForm(form): MultipartForm<UploadForm>) -> impl Responder {
    let mut s = String::new();
    for f in form.file {
        s.push_str(&format!(
            "Uploaded file {:?}, with size: {} \n",
            f.file_name, f.size
        ))
    }
    s
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(move || App::new().service(upload))
        .bind(("127.0.0.1", 8080))?
        .run()
        .await
}

请求

require "uri"
require "net/http"
url = URI("http://127.0.0.1:8080/upload")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
form_data = [['file', File.open('/file1')],['file', File.open('/file2')]]
request.set_form form_data, 'multipart/form-data'
response = http.request(request)
puts response.read_body

环境配置

版本信息

rustc --version
# => rustc 1.80.1 (3f5fd8dd4 2024-08-06)
cargo --version
# => cargo 1.80.1 (376290515 2024-07-16)

Crates

创建空目录, 初始化项目。添加 crate :

cargo add actix-web
cargo add actix-multipart

Cargo.toml

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

[dependencies]
actix-multipart = "0.7.2"
actix-web = "4.9.0"

参考

File upload in Actix Web
actix-multipart