W3docs

File API

The File API in JavaScript is a powerful tool that enables web developers to interact with files on the client-side.

File API in JavaScript: Interacting with User Files

The File API in JavaScript is a powerful tool that enables web developers to interact with files on the client-side, allowing users to select, read, and manipulate files within web applications. This API has several applications, including uploading files, processing user-generated content, and performing file-related operations. In this article, we'll explore what the File API is, its benefits, when to use it, and some common use cases.

What is the File API?

The File API is a JavaScript API that provides access to files selected by the user through file input fields (<input type="file">) or files dropped onto web pages. It exposes a small family of interfaces that work together:

  • File — represents a single file the user picked. It carries metadata such as name, size (in bytes), type (MIME type), and lastModified (a timestamp). A File is a special kind of Blob.
  • Blob — a chunk of immutable binary data ("Binary Large Object"). Every File is a Blob, but you can also build your own blobs to download or upload. See the dedicated JavaScript Blob chapter for more.
  • FileList — the array-like collection returned by input.files. Index it with [0] or iterate it.
  • FileReader — an asynchronous reader that pulls a file's contents into memory as text, a data URL, or an ArrayBuffer.

Because all of this runs in the browser, you can inspect, validate, and preview files before anything ever touches a server.

The File API only reads files the user explicitly hands you. A page can never silently open arbitrary files from the visitor's disk — that is a deliberate security boundary.

Reading methods at a glance

FileReader exposes four read methods. Pick the one that matches what you want back:

MethodResult typeTypical use
readAsText(file)string.txt, .csv, .json, source code
readAsDataURL(file)data: URL stringimage/audio/video previews via src
readAsArrayBuffer(file)ArrayBufferbinary parsing, hashing, byte inspection
readAsBinaryString(file)string of byteslegacy; prefer readAsArrayBuffer

Modern browsers also expose promise-based shortcuts directly on the blob: await file.text(), await file.arrayBuffer(), and file.stream(). These often replace FileReader in new code and pair naturally with async/await.

When to Use the File API

The File API is particularly useful when you want to:

  1. Handle file uploads — let users select and submit files from their devices.
  2. Preview files — show a thumbnail of a chosen image, or echo the text of a document, before uploading.
  3. Validate on the client — reject the wrong MIME type or an oversized file before spending bandwidth on an upload.
  4. Manipulate files locally — crop images, edit text, or parse CSV without a round trip to the server.

For PDFs note one caveat: the File API does not generate PDFs. It only selects, reads, and saves files. To create a PDF you need a library such as jsPDF, and the File API (via a Blob) can then trigger the download.

Basic Example: Reading File Contents

Here's a simple example using the File API in JavaScript to read a text file selected by the user and display its contents. This demo will help you understand how to interact with files on your devices using web technologies.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>File Reader Example</title>
  </head>
  <body>
    <h1>Read Text File</h1>
    <p>First, choose a text file, then click the 'Read File' button to see your file's contents.</p>
    <input type="file" id="fileInput" accept=".txt" />
    <button onclick="readFile()">Read File</button>
    <pre id="fileContents"></pre>

    <script>
      function readFile() {
        const fileInput = document.getElementById("fileInput");
        const file = fileInput.files[0]; // Get the first file selected by the user

        if (file) {
          const reader = new FileReader();

          reader.onload = function (e) {
            const contents = e.target.result;
            document.getElementById("fileContents").textContent = contents;
          };

          reader.onerror = function (e) {
            console.error("Error reading file:", e.target.error.message);
          };

          reader.readAsText(file); // Read the file as text
        } else {
          alert("Please select a file.");
        }
      }
    </script>
  </body>
</html>

In this code:

  • File Selection: The user selects a text file (a file with .txt extension) using the file input element.
  • Reading the File: When the user clicks the "Read File" button, the selected file is read as text. Note that FileReader operations are asynchronous; the onload callback executes only after the file has been fully read.
  • Displaying the File: The contents of the file are displayed in a <pre> element, preserving the formatting of the text file.

This example provides a straightforward demonstration of the File API's capability to read and interact with user-selected files in a web application.

Inspecting File Metadata

You often need a file's details before doing anything else — to validate it or to show the user what they picked. Every File object exposes this metadata synchronously, with no reading required:

const file = fileInput.files[0];

console.log(file.name);          // e.g. "report.pdf"
console.log(file.type);          // MIME type, e.g. "application/pdf"
console.log(file.size);          // size in bytes, e.g. 12048
console.log(file.lastModified);  // ms since the Unix epoch

A common task is turning the byte count into something human-readable:

function formatBytes(bytes) {
  if (bytes === 0) return "0 B";
  const units = ["B", "KB", "MB", "GB"];
  const i = Math.floor(Math.log(bytes) / Math.log(1024));
  return (bytes / Math.pow(1024, i)).toFixed(1) + " " + units[i];
}

console.log(formatBytes(0));        // "0 B"
console.log(formatBytes(900));      // "900.0 B"
console.log(formatBytes(2048));     // "2.0 KB"
console.log(formatBytes(5242880));  // "5.0 MB"

Validating Files Before Upload

Client-side validation gives the user instant feedback and saves a wasted upload. Always re-validate on the server too — client checks are a convenience, not a security guarantee, because anyone can bypass them.

function validateImage(file) {
  const allowedTypes = ["image/png", "image/jpeg", "image/webp"];
  const maxSize = 2 * 1024 * 1024; // 2 MB

  if (!allowedTypes.includes(file.type)) {
    return "Only PNG, JPEG, or WebP images are allowed.";
  }
  if (file.size > maxSize) {
    return "File is too large (max 2 MB).";
  }
  return null; // null means "valid"
}

// Simulate two checks:
console.log(validateImage({ type: "image/gif", size: 1000 }));
// "Only PNG, JPEG, or WebP images are allowed."
console.log(validateImage({ type: "image/png", size: 500 }));
// null

Previewing an Image Before Upload

To show a thumbnail of a chosen image, read it as a data URL and assign that string to an <img> element's src. The browser decodes the base64 payload directly — no server involved.

<input type="file" id="imageInput" accept="image/*" />
<img id="preview" alt="Preview" width="200" />

<script>
  const input = document.getElementById("imageInput");
  const preview = document.getElementById("preview");

  input.addEventListener("change", () => {
    const file = input.files[0];
    if (!file) return;

    const reader = new FileReader();
    reader.onload = (e) => {
      preview.src = e.target.result; // a "data:image/...;base64,..." URL
    };
    reader.readAsDataURL(file);
  });
</script>

For large media files, prefer URL.createObjectURL(file) instead of a data URL — it returns a short blob: reference without copying the whole file into a string. Remember to call URL.revokeObjectURL() when the preview is no longer needed so the browser can release the memory.

Reading a File With Modern Promises

In current browsers you can skip FileReader entirely and await the blob's own methods. This is cleaner when you're already inside an async function:

async function readTextFile(file) {
  const text = await file.text();
  return text.trim().split("\n").length; // count of lines
}

// Simulate a File with the same API as the real Blob:
const fakeFile = new Blob(["line 1\nline 2\nline 3"]);
readTextFile(fakeFile).then((lines) => console.log(lines)); // 3

Uploading a File to a Server

Once a file is selected you can send it with fetch and a FormData body. The browser sets the correct multipart/form-data headers automatically — do not set Content-Type yourself:

async function uploadFile(file) {
  const formData = new FormData();
  formData.append("upload", file, file.name);

  const response = await fetch("/api/upload", {
    method: "POST",
    body: formData,
  });
  return response.ok;
}

See the Fetch API chapter for the full request/response model.

Common Gotchas

  • FileReader is asynchronous. The result is only available inside onload; reading reader.result on the next line returns null.
  • input.files can hold multiple files. Add the multiple attribute to the input and iterate the FileList; otherwise you only ever see files[0].
  • The value clears on cancel in some browsers. Re-selecting the same file may not fire change; reset input.value = "" first if you need to detect it.
  • file.type can be empty. For unknown extensions the MIME type may be ""; never rely on it as your only check.
  • Object URLs leak memory. Each URL.createObjectURL() must be matched with a URL.revokeObjectURL().

Conclusion

The File API in JavaScript empowers web developers to work with user files directly within web applications, opening up possibilities for enhancing user interactions and providing a seamless user experience. Whether you're building a file uploader, a document editor, or any application that requires file manipulation, the File API equips you with the tools to create feature-rich, client-side file handling solutions.

To go further, explore the JavaScript Blob chapter for building and downloading your own binary data, Drag and Drop with JavaScript to let users drop files onto the page, and the Fetch API for sending files to a server.

Practice

Practice
What can you do with the File API in JavaScript?
What can you do with the File API in JavaScript?
Was this page helpful?