actix_extract_multipart

Crates.ioactix_extract_multipart
lib.rsactix_extract_multipart
version1.2.0
sourcesrc
created_at2021-05-28 20:28:07.586849
updated_at2022-08-15 14:44:32.130406
descriptionActixExtractMultipart is a library for parse actix_multipart into a structure that you defined
homepage
repositoryhttps://github.com/KosekiDev/ActixExtractMultipart
max_upload_size
id403305
size31,322
Vincent Bréhaut (KosekiDev)

documentation

README

ActixExtractMultipart

Functions and structures to handle actix multipart more easily. You can convert the multipart into a struct.

To use this function, you need to create a structure with "Deserialize" trait, like this:

#[derive(Deserialize)]
struct Example {
    string_param: String,
    optional_u_param: Option<u32>,
    files_param: Option<Vec<File>>
}

File is a structure for any files:

#[derive(Debug, Deserialize)]
pub struct File {
    file_type: String,
    name: String,
    data: FileData,
}
impl File {
    pub fn file_type(&self) -> &String {
        &self.file_type
    }
    pub fn name(&self) -> &String {
        &self.name
    }
    pub fn len(&self) -> usize {
        self.data.len()
    }
    pub fn data(&self) -> &FileData {
        &self.data
    }
}

FileData is an alias to Vec bytes:

pub type FileData = Vec<u8>;

Example of use

use actix_web::{post, App, HttpResponse, HttpServer};
use serde::{Deserialize};
use actix_extract_multipart::*;

#[derive(Deserialize)]
struct Example {
    string_param: String,
    optional_u_param: Option<u32>,
    file_param: File
}

fn saving_file_function(file: &File) -> Result<(), ()> {
    // Do some stuff here
    println!("Saving file \"{}\" successfully", file.name());

    Ok(())
}

#[post("/example")]
async fn index(example_structure: Multipart::<Example>) -> HttpResponse {    
    println!("Value of string_param: {}", example_structure.string_param);
    println!("Value of optional_u_param: {:?}", example_structure.optional_u_param);
    println!("Having file? {}", match example_structure.file_param {
        Some(_) => "Yes",
        None => "No"
    });

    if let Some(file) = &example_structure.file_param {
        match saving_file_function(&file) {
            Ok(_) => println!("File saved!"),
            Err(_) => println!("An error occured while file saving")
        }
    }

    HttpResponse::Ok().json("Done")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    println!("Server run at http://127.0.0.1:8080");

    HttpServer::new(move || {
        App::new()
            .service(index)
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

In this example, if you dont have received a file, extract_multipart will return an Err(_), because data don't correspond to the data struct "Example". If the File is optional, you can simply set the type as Option, like this:

#[derive(Deserialize)]
struct Example {
    string_param: String,
    optional_u_param: Option<u32>,
    file_param: Option<File>
}

In the case of Vec, don't forget to put hooks at the end of the field name. You can also have any other type array like Vec, Vec etc... In the follow html exemple, you can notice that the file's field's name contain hooks: name="files_param[]". It's important, without hooks, this code will not work.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Testing</title>
    <script>
        function send() {
            let myHeaders = new Headers();
            let formdata = new FormData(document.getElementById('form'));
            let myInit = { method: 'POST', headers: myHeaders, body: formdata };
            fetch("http://127.0.0.1:8082/example", myInit)
            .then(() => {
                console.log("It works!")
            })
            .catch((e) => {
                console.log("Error!\n" + e)
            })
        }
    </script>
</head>
<body>
    <form id="form">
        <input type="file" name="files_param[]" multiple>
        <button type="button" onclick="send()">OK</button>
    </form>
</body>
</html>
Commit count: 47

cargo fmt