| 71 | /// Example of the old manual way of processing multipart forms. |
| 72 | #[allow(unused)] |
| 73 | async fn save_file_manual(mut payload: Multipart) -> Result<HttpResponse, Error> { |
| 74 | // iterate over multipart stream |
| 75 | while let Some(mut field) = payload.try_next().await? { |
| 76 | // A multipart/form-data stream has to contain `content_disposition` |
| 77 | let Some(content_disposition) = field.content_disposition() else { |
| 78 | continue; |
| 79 | }; |
| 80 | |
| 81 | let filename = content_disposition |
| 82 | .get_filename() |
| 83 | .map_or_else(|| Uuid::new_v4().to_string(), sanitize_filename::sanitize); |
| 84 | let filepath = format!("./tmp/{filename}"); |
| 85 | |
| 86 | // File::create is blocking operation, use threadpool |
| 87 | let mut f = web::block(|| std::fs::File::create(filepath)).await??; |
| 88 | |
| 89 | // Field in turn is stream of *Bytes* object |
| 90 | while let Some(chunk) = field.try_next().await? { |
| 91 | // filesystem operations are blocking, we have to use threadpool |
| 92 | f = web::block(move || f.write_all(&chunk).map(|_| f)).await??; |
| 93 | } |
| 94 | } |
| 95 | |
| 96 | Ok(HttpResponse::Ok().into()) |
| 97 | } |