For a Pure JS, you can use fetch optionally with await-try-catch as mentioned below:-
let photo = document.getElementById("image-file").files[0];
let formData = new FormData();
formData.append("photo", photo);
fetch('/upload/image', {method: "POST", body: formData});
Old school approach - xhr
let photo = document.getElementById("image-file").files[0]; // file from input
let req = new XMLHttpRequest();
let formData = new FormData();
formData.append("photo", photo);
req.open("POST", '/upload/image');
req.send(formData);
Basically, On the server side you can read the original file name (and other info) which is automatically included to request by browser in filename formData parameter.
You do NOT need to set the request header Content-Type to multipart/form-data - this will be set automatically by browser. Instead of /upload/image you can use a full address like http://.../upload/image. If you want to send many files in single request use multiple attribute: <input multiple type=... />, and attach all chosen files to formData in a similar way (e.g. photo2=...files[2];...) You can include additional data (json) to request e.g. let user = {name:'john', age:34} in this way: formData.append("user", JSON.stringify(user)); You can set timeout: for fetch using AbortController, for old approach by xhr.timeout= milisec. This solution should work on all major browsers.