// HTML part:
// <input type="file" id="fileInput" />
// <button onclick="uploadFile()">Upload</button>
// <progress id="uploadProgress" value="0" max="100"></progress>
use leptos::*;
use wasm_bindgen::JsCast;
use web_sys::{Event, HtmlInputElement, ProgressElement, XmlHttpRequest};
#[component]
pub fn FileUploader(cx: Scope) -> Element {
view! { cx,
<input id="fileInput" type="file" />
<button on:click=move |_| upload_file() >"Upload"</button>
<progress id="uploadProgress" value="0" max="100"></progress>
}
}
fn upload_file() {
let window = web_sys::window().expect("no global `window` exists");
let document = window.document().expect("should have a document on window");
let file_input: HtmlInputElement = document
.get_element_by_id("fileInput")
.expect("fileInput not found")
.dyn_into::<HtmlInputElement>()
.expect("fileInput should be an HtmlInputElement");
let file = match file_input.files().and_then(|files| files.get(0)) {
Some(file) => file,
None => {
web_sys::window()
.unwrap()
.alert_with_message("Please select a file to upload.")
.unwrap();
return;
}
};
let form_data = web_sys::FormData::new().unwrap();
form_data.append_with_blob("file", &file).unwrap();
let xhr = XmlHttpRequest::new().unwrap();
xhr.open_with_async("POST", "https://your-server-endpoint/upload", true)
.unwrap();
let progress_element: ProgressElement = document
.get_element_by_id("uploadProgress")
.expect("uploadProgress not found")
.dyn_into::<ProgressElement>()
.expect("uploadProgress should be a ProgressElement");
let upload_clone = xhr.upload().unwrap();
let progress_callback = Closure::wrap(Box::new(move |event: Event| {
let progress_event = event.dyn_ref::<web_sys::ProgressEvent>().unwrap();
if progress_event.length_computable() {
let percent_complete = (progress_event.loaded() as f64 / progress_event.total() as f64) * 100.0;
progress_element.set_value(percent_complete);
}
}) as Box<dyn FnMut(_)>);
upload_clone.set_onprogress(Some(progress_callback.as_ref().unchecked_ref()));
progress_callback.forget();
let ready_state_callback = Closure::wrap(Box::new(move || {
if xhr.ready_state() == 4 {
if xhr.status() == 200 {
log::info!("File uploaded successfully: {:?}", xhr.response_text().unwrap());
} else {
log::error!("Error uploading file: {:?}", xhr.status_text());
}
}
}) as Box<dyn FnMut()>);
xhr.set_onreadystatechange(Some(ready_state_callback.as_ref().unchecked_ref()));
ready_state_callback.forget();
xhr.send_with_opt_form_data(Some(&form_data)).unwrap();
}