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
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)
}