Question

Preview an Image Before Uploading with JavaScript

javascriptjqueryfile-upload

Question

How can I preview an image selected through an <input type="file"> before uploading it? The preview must happen entirely in the browser, without using Ajax or sending the image to a server.

Short Answer

You will learn how browser file inputs expose selected files to JavaScript and how to display an image preview locally with URL.createObjectURL(). You will also learn to validate file types, clean up temporary Blob URLs, and handle the case where no file is selected.

Concept

A file input lets a user choose a file from their device:

<input type="file" accept="image/*">

Choosing a file does not upload it automatically. Instead, the browser makes information about the selected file available through the input element's files collection. JavaScript can use that local File object to create a temporary URL and assign it to an image element.

const file = fileInput.files[0];
const previewUrl = URL.createObjectURL(file);
image.src = previewUrl;

The image is read locally by the browser. No network request, Ajax request, or server code is required.

This matters because previews improve user experience: people can confirm that they selected the right profile picture, product image, attachment, or document before submitting a form. The actual upload can happen later, only after the user confirms the form.

Mental Model

Think of a selected file as a photo handed to the browser for inspection, not delivery. The browser has the photo temporarily in hand, but it has not mailed it to a server.

URL.createObjectURL(file) creates a temporary local label that an <img> element can use to find and display that photo. When the preview is no longer needed, remove the label with URL.revokeObjectURL().

  • File: the locally selected image
  • Blob URL: a temporary local address for that image
  • <img>: the frame that displays the image
  • Upload: a separate action that sends the image to a server
Take Quiz

Syntax and Examples

Use the input's change event to detect a new selection. Get the first selected file from event.target.files, then use an object URL as the image source.

<label for="imageInput">Choose an image</label>
<input id="imageInput" type="file" accept="image/*">

<img id="preview" alt="Selected image preview" hidden>

<script>
  const imageInput = document.querySelector('#imageInput');
  const preview = document.querySelector('#preview');

  imageInput.addEventListener('change', (event) => {
    const file = event.target.files[0];

    if (!file) {
      preview.hidden = true;
      preview.removeAttribute('src');
      return;
    }

    const imageUrl = URL.createObjectURL(file);
    preview.src = imageUrl;
    preview.hidden = false;

    preview.addEventListener('load', () => {
      URL.revokeObjectURL(imageUrl);
    }, { once: true });
  });
</script>

accept="image/*" helps users choose images in the file picker. It is a convenience, not a security check, so JavaScript should still verify the file type when appropriate.

The load listener revokes the temporary URL after the browser has loaded the image. This avoids retaining unnecessary memory when users preview several files.

Step by Step Execution

Consider this example:

imageInput.addEventListener('change', (event) => {
  const file = event.target.files[0];

  if (!file) return;

  if (!file.type.startsWith('image/')) {
    alert('Please choose an image file.');
    return;
  }

  const imageUrl = URL.createObjectURL(file);
  preview.src = imageUrl;
});
  1. The user chooses a file in the operating system's file picker.
  2. The browser fires the input's change event.
  3. event.target.files[0] retrieves the first selected File object.
  4. If the user cancelled the picker or cleared the field, file is missing and the function stops.
  5. file.type.startsWith('image/') checks whether the browser reports an image MIME type, such as image/jpeg or image/png.
  6. URL.createObjectURL(file) creates a temporary Blob URL, such as blob:https://example.com/....
  7. Assigning that URL to preview.src tells the <img> element to render the local file.
  8. At no point does this code call fetch, XMLHttpRequest, or submit a form, so nothing is uploaded.

Real World Use Cases

  • Profile photo forms: Let users verify their portrait before saving account changes.
  • E-commerce dashboards: Preview a product photo before creating or updating a listing.
  • Content management systems: Show article cover-image previews before an editor publishes.
  • Support forms: Let users inspect an image attachment before submitting a support request.
  • Image editing tools: Display a selected local image before applying client-side transformations such as cropping or resizing.
  • Multi-file galleries: Render thumbnails for several selected images before the user chooses which ones to upload.
Take Quiz

Real Codebase Usage

In production code, previews are usually combined with validation, state cleanup, and accessible feedback.

Validate early with guard clauses

function showPreview(file) {
  if (!file) return;

  if (!file.type.startsWith('image/')) {
    throw new Error('Only image files are allowed.');
  }

  if (file.size > 5 * 1024 * 1024) {
    throw new Error('The image must be 5 MB or smaller.');
  }

  return URL.createObjectURL(file);
}

Replace old preview URLs

If users select multiple files one after another, revoke the old URL before creating a new one.

let currentPreviewUrl = null;

imageInput.addEventListener('change', (event) => {
  const file = event.target.files[0];

  if (currentPreviewUrl) {
    URL.revokeObjectURL(currentPreviewUrl);
    currentPreviewUrl = null;
  }

  if (!file || !file.type.startsWith('image/')) return;

  currentPreviewUrl = URL.createObjectURL(file);
  preview.src = currentPreviewUrl;
  preview.hidden = false;
});

Keep preview separate from upload

A preview is only local UI state. The selected File can later be sent using a normal form submission or FormData, but that is a separate step from displaying it.

Client-side checks improve feedback, but server-side validation is still required when the file is eventually uploaded. Client-side code can be bypassed.

Common Mistakes

Trying to read the input's value as an image URL

This does not give JavaScript a usable local file path, and browsers intentionally restrict access to real paths for security.

// Do not rely on this.
preview.src = imageInput.value;

Use imageInput.files[0] and URL.createObjectURL() instead.

Forgetting that the user may cancel the picker

files[0] may be missing. Always check it first.

const file = event.target.files[0];
if (!file) return;

Trusting accept="image/*" as validation

The accept attribute filters the file picker but does not guarantee the selected file is safe or truly valid. Check file.type for user feedback, and validate again on the server when uploading.

Creating many Blob URLs without revoking them

Repeated calls to URL.createObjectURL() can retain memory until URLs are revoked or the page is unloaded. Revoke an old URL when replacing a preview, or revoke it after the image loads when it is no longer needed.

Using FileReader when a Blob URL is enough

FileReader.readAsDataURL() works, but it converts file data into a long Base64 string. For a simple <img> preview, object URLs are usually simpler and more memory-efficient.

Assuming a preview means the file was uploaded

Displaying an image only renders local data. An explicit form submission or upload request is still needed to send it to a server.

Comparisons

ApproachBest useResultNotes
URL.createObjectURL(file)Displaying a local file in an image, video, or download linkTemporary Blob URLUsually the simplest option for previews; revoke the URL when finished.
FileReader.readAsDataURL(file)When code specifically needs a Base64 data URLdata:image/...;base64,... stringCan be larger in memory; no manual object-URL cleanup.
input.valueIdentifying that an input has a selectionBrowser-controlled stringDo not use it as a real local path or preview source.
Uploading with fetch or form submissionSending a file to a serverNetwork requestNot required for a client-side preview.

URL.createObjectURL() and FileReader both work without uploading. Choose an object URL for ordinary previews and FileReader only when you need the file contents in a JavaScript-readable format.

Take Quiz

Cheat Sheet

<input id="fileInput" type="file" accept="image/*">
<img id="preview" alt="Image preview" hidden>
const fileInput = document.querySelector('#fileInput');
const preview = document.querySelector('#preview');
let previousUrl;

fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];

  if (previousUrl) URL.revokeObjectURL(previousUrl);

  if (!file || !file.type.startsWith('image/')) {
    preview.hidden = true;
    preview.removeAttribute('src');
    return;
  }

  previousUrl = URL.createObjectURL(file);
  preview.src = previousUrl;
  preview.hidden = false;
});
  • Get a selected file with input.files[0].
  • Use URL.createObjectURL(file) for a local preview URL.
  • Use accept="image/*" to guide file selection.
  • Check file.type.startsWith('image/') before previewing.
  • Check file.size if your application has size limits.
  • Revoke replaced Blob URLs with URL.revokeObjectURL(url).
  • A preview does not upload the file.
  • Validate files on the server too when an upload occurs.

FAQ

Can JavaScript preview an image without uploading it?

Yes. Use the File selected from an <input type="file"> and assign an object URL to an <img> element. This happens entirely in the browser.

Does URL.createObjectURL() send the image to a server?

No. It creates a temporary local Blob URL inside the browser. It does not make a network request.

Should I use FileReader or URL.createObjectURL for image previews?

For a normal image preview, use URL.createObjectURL(). Use FileReader.readAsDataURL() when you specifically need a Base64 data URL.

Why can I not use the file input value as the image source?

Browsers do not expose a real local path to page JavaScript for security reasons. Use the files collection instead.

How do I limit the file picker to images?

Add accept="image/*" to the file input. Also validate file.type in JavaScript because accept is not a security boundary.

How do I preview multiple selected images?

Use input.files, loop through each File, create an object URL for each one, and create an <img> element for every preview.

Do I need to revoke an object URL?

You should revoke it when replacing or discarding a preview, especially in long-running pages where users may choose many files.

Take Quiz

Mini Project

Description

Build a profile-image picker that previews a selected image without uploading it. The interface should reject non-image files, reject files larger than 2 MB, show a message for validation errors, and allow the user to remove the chosen image.

Goal

Create a local image preview that can be selected, validated, replaced, and removed entirely in the browser.

Requirements

Use a file input that guides users toward image files. Validate that the selected file is an image. Reject files larger than 2 MB and show an error message. Show the selected image only after it passes validation. Provide a button that clears the preview and selected file.

Take Quiz

Keep learning

Related questions

View more