I am trying to create a file-upload function in Actix web. This to save files uploaded from the client who uses something like <input type="file" name="myFile"> for example.
But I am stuck, this is what I have:
pub mod files {
use actix_form_data::{Error, Field, Form, Value};
use actix_multipart::Multipart;
use actix_web::{
web::{post, resource, Data},
App, HttpResponse, HttpServer,
};
use futures::Future;
use std::path::PathBuf;
use uuid::Uuid;
async fn upload(uploaded_content: Value) -> HttpResponse {
println!("Uploaded Content: {:#?}", uploaded_content);
HttpResponse::Created().finish()
}
}
This is all I can find in the documentation or the internet. How would I continue from this? How to write uploaded_content to a file?
You can match on this enum to extract the information you need, then do what you want with it. The enum has a few convenience methods that will let you avoid the match in some cases, and I encourage you to click the [src] button on them to learn what they do if it's not clear from their name.
pub mod files {
use std::io::Write;
use actix_multipart::Multipart;
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
use futures::{StreamExt, TryStreamExt};
pub async fn save_file(mut payload: Multipart, file_path: String) -> Option<bool> {
// iterate over multipart stream
while let Ok(Some(mut field)) = payload.try_next().await {
let content_type = field.content_disposition().unwrap();
//let filename = content_type.get_filename().unwrap();
let filepath = format!(".{}", file_path);
// 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
.unwrap();
}
}
Some(true)
}
}