Skip to content
Snippets Groups Projects
mock_upload.rs 2.69 KiB
Newer Older
use formdata::{read_formdata, FilePart};
use routing::request::ConvertedHeaders;
Louis's avatar
Louis committed
use hyper::header::{ContentDisposition, DispositionParam};
use std::io::{copy};
use std::fs::{OpenOptions, File, create_dir};
use cli::{HandlerMethod, SwerveConfig};
Louis's avatar
Louis committed
use std::path::{PathBuf};
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),
        }

Louis's avatar
Louis committed
        match create_dir("uploads") {
			Ok(_) => {},
			Err(err) => {
				return Err(format!("Could not create uploads directory:\n{}", err));
			}
		}
        for file in data.files {
            match conf.file_handling {
                HandlerMethod::Log => log_file(file),
                HandlerMethod::File => upload_file(file),
    } else {
        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();
Louis's avatar
Louis committed
    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)
Louis's avatar
Louis committed
        .open(PathBuf::from("uploads").join(file_name.clone()))
        .unwrap();

    copy(&mut input, &mut output).unwrap();
Louis's avatar
Louis committed
    println!("File written to {}", file_name);
}

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