I'm trying to handle POST requests on my webserver for file uploads, but i haven't found good documentation or examples on how to do it.
Here is the POST function i came up with after a long time:
#[post("/upload",data="<file>")]
fn upload_handler(file: Data) -> Redirect {
let mut buffer = Vec::new();
file.stream_to(&mut buffer).unwrap();
let split_pos = buffer.windows(4).position(|pos|pos == b"\r\n\r\n").unwrap();
let split_end = buffer.windows(8).position(|pos|pos == b"\r\n------").unwrap();
let headers = String::from_utf8_lossy(&buffer[0..split_pos]);
let content = &buffer[split_pos+4..split_end];
println!("{}",&headers);
let re = Regex::new("filename=\"(?P<filename>.*)\"").unwrap();
let captures = re.captures(&headers).unwrap();
let filename = &captures["filename"].to_owned();
let mut local_file = File::create(filename).unwrap();
local_file.write(content).unwrap();
Redirect::to("/")
}
It kinda works but has a lot of flaws like:
- I can't limit the file upload size.
- I don't know the size of the file being uploaded.
- I had to manually regex the filename (which i don't think is a thing you have to do when using a framework).
- I can't see the entire request header.
When spliting the headers from the content this is all i got:
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: image/jpeg
Here's a simple working code i had on a python flask server that did the job:
@app.route("/upload",methods=["POST"])
def upload():
if int(request.headers["Content-Length"]) > app.config["MAX_CONTENT_LENGTH"]:
abort(413)
f = request.files["file"]
filename = secure_filename(f.filename)
if filename.endswith(ALLOWED_EXTENSIONS):
f.save("src/"+filename)
return render_template("upload.html",file=filename),{"Refresh": "2; url=/"}
else:
return render_template("denied.html")
If anyone knows a better/right way of doing it please tell me.