use std::io::Write; use actix_multipart::Multipart; use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer}; use futures::StreamExt; async fn save_file(mut payload: Multipart) -> Result { // iterate over multipart stream while let Some(item) = payload.next().await { let mut field = item?; let content_type = field.content_disposition().unwrap(); let filename = content_type.get_filename().unwrap(); let filepath = format!("./tmp/{}", filename); // File::create is blocking operation, use threadpool let mut f = web::block(|| std::fs::File::create(filepath)) .await .unwrap(); // Field in turn is stream of *Bytes* object while let Some(chunk) = field.next().await { let data = chunk.unwrap(); // filesystem operations are blocking, we have to use threadpool f = web::block(move || f.write_all(&data).map(|_| f)).await?; } } Ok(HttpResponse::Ok().into()) } fn index() -> HttpResponse { let html = r#" Upload Test
"#; HttpResponse::Ok().body(html) } #[actix_rt::main] async fn main() -> std::io::Result<()> { std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info"); std::fs::create_dir_all("./tmp").unwrap(); let ip = "0.0.0.0:3000"; HttpServer::new(|| { App::new().wrap(middleware::Logger::default()).service( web::resource("/") .route(web::get().to(index)) .route(web::post().to(save_file)), ) }) .bind(ip)? .start() .await }