0

Rust warp multipart. How to post photo with warp and then save it as file?

I've tried this code:

pub async fn photos(form: warp::multipart::FormData) -> Result<impl Reply, Rejection> {
    let parts: Vec<Part> = form.try_collect().await.map_err(|e| {
        eprintln!("form error: {}", e);
        warp::reject::reject()
    })?;

    for p in parts {
        eprintln!("{:#?}", p);

        let filename = p.filename().unwrap_or("photo.png");
        let filepath = format!("uploads/{}", filename);

        fs::create_dir_all("uploads").unwrap();
        let mut file = fs::File::create(&filepath).unwrap();

        let data = p.stream().next().await;
        file.write_all(data.unwrap().unwrap().chunk()).unwrap();
    }
    /* 

    while let Some(chunk) = photo.stream().try_next().await? {
        file.write_all(&chunk.chunk()).unwrap();
    } */

    Ok("Upload successful!")
}

but when I send photo is says: form error: failed to lock multipart state

AmALAks
  • 3
  • 2

1 Answers1

0

Here is solution that i came to:

pub async fn photos(form: warp::multipart::FormData) -> Result<impl Reply, Rejection> {
    task::spawn(async move {
        let mut parts = form.into_stream();

        while let Ok(p) = parts.next().await.unwrap() {
            let filename = p.filename().unwrap_or("photo.png");
            let filepath = format!("uploads/{}", filename);

            fs::create_dir_all("uploads").unwrap();

            save_part_to_file(&filepath, p).await.expect("save error");
        }
    });

    Ok("Upload successful!")
}

async fn save_part_to_file(path: &str, part: warp::multipart::Part) -> Result<(), std::io::Error> {
    let data = part
        .stream()
        .try_fold(Vec::new(), |mut acc, buf| async move {
            acc.extend_from_slice(buf.chunk());
            Ok(acc)
        })
        .await.expect("folding error");
    std::fs::write(path, data)
}
AmALAks
  • 3
  • 2