-
Notifications
You must be signed in to change notification settings - Fork 111
Description
I have problems uploading multipart form data from HTML/Javascript to my rouille server.
In the server I use the rouille::input::post routines.
It works very well for all kind of files BUT NOT for plain/text files. I cannot make it accept any .txt files.
The input::post::BufferedFile sets the slot (quite often) to None for plain/text files (maybe it lacks info about the file's MIME Type, plain/text).
See the cases when it works and when not.
The test-program:
THESE FAIL:
These curl and httpie commands fail. Server does not recognize the test1.txt file (cannot dertermine its MIME?).
curl -X POST --form "field1=112" --form "field2=Booom" --form "files=@test1.txt" --form "files=@test2.json" http://localhost:8000/post
http --verify=no --form post http://localhost:8000/post field1=112 field2="Booom!" files@'test1.txt' files@'test2.json'
THESE ARE OK:
These commands work right, the server receives the files and all good. Setting the MIME type manually.
test1.txt; type=plain/text
test2.json; type=application/json
curl --form "field1=112" --form "field2=Booom" --form "files=@test1.txt;type=plain/text" --form "files=@test2.json;type=application/json" http://localhost:8000/post
http --verify=no --form post http://localhost:8000/post field1=112 field2="Booom!" files@'test1.txt;type=plain/text' files@'test2.json;type=application/octet-stream'
POSTING FROM HTML/JS FAILS TO UPLOAD .TXT:
Also, when I post form-data from HTML/Javascript, the server fails to see the *.txt files. I have not managed to set the MIME type in Javascript. Start the rust-server and navigate your browser to http://localhost:8000
Then pick some files (.txt and other types).
Here is the code and Cargo.toml file:
(Sorry for the bad formatting and tabs... I do not know what happened. wth*)
use rouille::{router, Response, Request};
use rouille::input::post::BufferedFile;
fn main() {
println!("Navigate to localhost:8000");
rouille::start_server("localhost:8000", move |req| {
let resp = router!(req,
(GET) (/) => {
rouille::Response::html(get_index_html())
},
(POST) (/post) => {
test_multipart(req)
},
_ => rouille::Response::empty_404()
);
resp
});
}
pub fn test_multipart(req: &Request) -> rouille::Response {
let res = rouille::post_input!(req, {
field1: Option<u32>,
field2: Option<String>,
files: Vec<Option<BufferedFile>>,
});
if let Err(e) = res {
return Response::text(format!("Got error: {}", e));
}
let inp = res.unwrap();
println!("Formdata, Got data : {:?}", inp);
println!("------------------------------------");
let mut count = 0;
for item in inp.files.iter() {
if let Some(f) = item {
println!("Filename:{}", f.filename.as_ref().unwrap());
println!("Mime:{}", f.mime);
println!("File len:{}", f.data.len());
count += 1;
} else {
println!("File slot is None !");
}
println!("--------");
}
let s = format!("The size of BufferedFile vector is:{}. Found {} files. ", inp.files.len(), count);
println!("{s}");
Response::text(s)
}
fn get_index_html() -> &'static str {
let html = r###"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.cl {
margin-bottom: 20px;
}
</style>
</head>
<body>
<br>
<form method="post" action="http://127.0.0.1:8000/post" enctype="multipart/form-data">
Field1 number: <br>
<input class="cl" type="number" name="field1"><br>
Field2 txt: <br>
<input class="cl" type="text" name="field2"><br>
<label for="file">Multiple files:</label><br>
<input id="some-files" class="cl" type="file" name="files" multiple/>
<!-- <input type="file" class="cl" id="form-files" name="files" accept="image/*,.pdf,.txt" multiple /> -->
<br>
<button id="submit-me" class="cl" style="width:100px; height:50px;">Send data...</button>
<br>
<div id="result"></div>
</form>
<script>
const btn_submit = document.getElementById("submit-me");
btn_submit.addEventListener("click", (event) => {
event.preventDefault();
send_data();
});
const inp_files = document.querySelector("#some-files");
const div_result = document.querySelector("#result");
async function send_data() {
const form = new FormData();
form.append("field1", "123");
form.append("field2", "some text");
for (i=0; i< inp_files.files.length; i++) {
console.log("Adding file:" + inp_files.files[i].name);
form.append("files", inp_files.files[i]);
//data.append('files', inp_files.files[i], { type: "text/plain" });
}
fetch("http://localhost:8000/post", {
method: "POST",
body: form,
mode: 'no-cors',
headers: {
'Access-Control-Allow-Origin' : '*'
},
})
.then((response) => {
return response.text();
})
.then((data) => {
div_result.innerText = data;
})
.catch(function(e) {
div_result.innerText = e;
});
}
</script>
</body>
</html>"###;
html
}
Cargo.toml file:
[package]
name = "T1"
version = "0.1.0"
edition = "2024"
[dependencies]
rouille = "3.6.2"
I forgot.
My desktop is Ubuntu Linux 24.10.
Browser is Chrome Version 135.0.7049.52 (Official Build) (64-bit)
Server is Ubuntu too.