Newer
Older
use rocket::{Data, State};
use formdata::{read_formdata, FilePart};
use hyper::header::{ContentDisposition, DispositionParam};
use std::io::{copy};
use std::fs::{OpenOptions, File, create_dir};
use cli::{HandlerMethod, SwerveConfig};
use std::collections::HashMap;
#[post(path = "/", data = "<upload>")]
pub fn to_file(headers: ConvertedHeaders, conf: State<SwerveConfig>, upload: Data) -> Result<String, String> {
let formdata = read_formdata(&mut upload.open(), &headers.as_hyper());
if let Ok(data) = formdata {
let fields = collect_fields(data.fields);
match conf.field_handling {
HandlerMethod::Log => println!("{:?}", fields),
HandlerMethod::File => println!("{:?}", fields),
}
match create_dir("uploads") {
Ok(_) => {},
Err(err) => {
return Err(format!("Could not create uploads directory:\n{}", err));
}
}
match conf.file_handling {
HandlerMethod::Log => log_file(file),
HandlerMethod::File => upload_file(file),
Ok(String::from("Complete"))
Err(String::from("Failed"))
}
}
fn collect_fields(fields: Vec<(String, String)>) -> HashMap<String, String> {
let mut map = HashMap::with_capacity(fields.len());
'collector: for (key, value) in fields {
if value == String::from("undefined") { continue 'collector };
map.insert(key.clone(), value.clone());
}
map
}
type Upload = (String, FilePart);
fn upload_file(file: Upload) {
let (name, value) = file;
let content_disposition = value.headers.get::<ContentDisposition>().unwrap();
let file_name = filename_from_disposition(content_disposition).unwrap_or(name);
let mut input = File::open(value.path.clone()).unwrap();
let mut output = OpenOptions::new()
.write(true)
.create(true)
.open(PathBuf::from("uploads").join(file_name.clone()))
.unwrap();
copy(&mut input, &mut output).unwrap();
}
fn log_file(file: Upload) {
let (name, value) = file;
println!("[UPLOAD] From field: {}. Size: {}", name, value.size.unwrap_or(0));
for header in value.headers.iter() {
println!("[UPLOAD] :: {}; {}", header.name(), header.value_string());
}
}
fn filename_from_disposition(dispo: &ContentDisposition) -> Option<String> {
for param in dispo.parameters.iter() {
if let &DispositionParam::Filename(_, _, ref name_vec) = param {
return Some(String::from_utf8(name_vec.to_vec()).unwrap_or(String::from("bad_filename.bin")));
}