actix-webでMultipartを受け取る

actix-webでMultipartなデータを受け取る方法を調べたのでメモ。

環境

  • rustc: 1.69.0
  • actix-web: 4.3.1
  • actix-multipart: 0.6.0

参考

サンプル

Multipartをactix-webで扱うためのcrateは色々ありそうだが、参考にしたコードの通りactix-multipartを使った。

ハンドラは以下のように定義できる。

use actix_web::{post, Result, Responder};
use actix_multipart::Multipart;
use tokio::fs;
use tokio::io::AsyncWriteExt;

#[post("/csv")]
pub async fn handle_post_csv(
    mut payload: Multipart,  // ここでMultipartを受け取る
) -> Result<impl Responder> {
    let dir = "./uploads";
    let mut sum: usize = 0;
    while let Ok(Some(mut field)) = payload.try_next().await {
        let dest = format!(
            "{}/{}",
            dir,
            field.content_disposition().get_filename().unwrap()
        );
        let mut f = fs::File::create(&dest).await?;
        while let Ok(Some(chunk)) = field.try_next().await {
            f.write_all(&chunk).await.unwrap();
        }
    }
    Ok()
}

以下のようにcurlで送信すると、./uploadsにファイルが保存される。

$ curl -F file=test1.csv http://localhost:8080/csv