What is the correct way to upload a file using JavaScript, and how can I send it to a server while listening for upload completion?

I have an <input type="file"> element on my page:

<input id="image-file" type="file" />

This lets users select a file through the browser’s file dialog. Once a file is chosen, its path is stored in:

document.getElementById("image-file").value

What and how should I use an upload file JavaScript approach to send this file to a server endpoint like “/upload/image” via a multipart POST request?

Also, how can I detect when the upload has successfully completed and possibly show a success message or trigger another action?

One of the most classic ways to handle file uploads in JavaScript is by using FormData with XMLHttpRequest. It gives you good control over the request and lets you listen for progress or completion events.

function uploadFile() {
  const fileInput = document.getElementById("image-file");
  const file = fileInput.files[0];

  const formData = new FormData();
  formData.append("file", file);

  const xhr = new XMLHttpRequest();
  xhr.open("POST", "/upload/image");

  xhr.onload = function () {
    if (xhr.status === 200) {
      console.log("Upload complete!");
    } else {
      console.error("Upload failed.");
    }
  };

  xhr.send(formData);
}

If you’re looking to upload file JavaScript style with full control, this is a solid, browser-friendly choice, especially for handling things like progress bars and response handling.

If you’re working in a modern browser, fetch() is a neat alternative that keeps your code simple and promises-based.

async function uploadFile() {
  const fileInput = document.getElementById("image-file");
  const file = fileInput.files[0];

  const formData = new FormData();
  formData.append("file", file);

  try {
    const response = await fetch("/upload/image", {
      method: "POST",
      body: formData
    });

    if (response.ok) {
      console.log("File uploaded successfully!");
    } else {
      console.error("Upload failed.");
    }
  } catch (err) {
    console.error("An error occurred:", err);
  }
}

This is my personal favorite for a modern workflow. Clean, promise-based, and very readable.