Hess WebTech

Build It Right. Support It Well.

A quick tour of the Web File API

Document Management System (DMS) being setup by IT consultant

Modern web apps often need to work with local files—previewing an image before upload, importing a CSV, or reading a text document to populate an editor. The File API is the foundational Web API that makes this possible by letting a page read files the user explicitly provides.

What the File API is for

The File API enables web applications to access files and their contents when the user makes them available, typically through:

When files are provided this way, the browser exposes them to your code as a FileList, which contains one or more File objects.

The core building blocks

There are also handy URL helpers:

How it relates to other file APIs

The File API is the most basic of the web’s file-related APIs: it focuses on reading and processing data the user provides via input or drag-and-drop, including handling binary data via blobs.

				
					<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File API Demo</title>
    <link href="style.css" rel="stylesheet" />
    <script src="file_API.js" defer></script>
</head>
    
<body>
    <div class="container">
        <header>
            <h1>File API Overview</h1>
            <p>Select a file or drag-and-drop to inspect metadata and read content.</p>
        </header>
    
        <!-- Method 1: Standard Input -->
        <div class="control-group">
            <label for="file-input" class="btn primary">Choose File(s)</label>
            <input type="file" id="file-input" multiple hidden>
            <span id="file-count">No files chosen</span>
        </div>
    
        <!-- Method 2: Drag and Drop Zone -->
        <div id="drop-zone" class="drop-zone">
            <p>📂 Drag & Drop files here</p>
        </div>
    
        <!-- Output Log -->
        <section class="output-area">
            <h3>File Details & Content:</h3>
            <pre id="output">Waiting for interaction...</pre>
            <div id="preview-container"></div>
        </section>
    </div>
</body>

</html>
				
			
				
					:root {
    --bg-color: #1e1e1e;
    --text-color: #e0e0e0;
    --card-bg: #2d2d2d;
    --primary: #4caf50;
    --accent: #2196f3;
    --border: #444;
}

body {
    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    background-color: var(--bg-color);
    color: var(--text-color);
    display: flex;
    justify-content: center;
    padding: 2rem;
    line-height: 1.6;
}

.container {
    max-width: 700px;
    width: 100%;
}

/* Hide standard input, style label as button */
.btn {
    display: inline-block;
    padding: 10px 20px;
    background-color: var(--primary);
    color: white;
    border-radius: 4px;
    cursor: pointer;
    font-weight: bold;
    transition: opacity 0.2s;
}

.btn:hover {
    opacity: 0.9;
}

/* Drag and Drop Zone */
.drop-zone {
    margin: 20px 0;
    border: 2px dashed var(--border);
    border-radius: 8px;
    padding: 40px;
    text-align: center;
    background-color: var(--card-bg);
    transition: border-color 0.3s, background-color 0.3s;
}

/* Class added via JS when dragging over */
.drop-zone.hover {
    border-color: var(--accent);
    background-color: #2196f320;
    /* Transparent blue */
}

/* Output Area */
.output-area {
    margin-top: 20px;
    padding: 15px;
    background-color: #000;
    border-radius: 4px;
    border: 1px solid var(--border);
}

#output {
    white-space: pre-wrap;
    font-family: 'Consolas', monospace;
    color: #a5d6a7;
}

img.preview-thumb {
    max-width: 150px;
    margin-top: 10px;
    border: 1px solid #fff;
}
				
			
				
					/**
 * Spec Steppin' Series: File API Overview
 * Source: https://developer.mozilla.org/en-US/docs/Web/API/File_API
 */

const fileInput = document.querySelector('#file-input');
const fileCountSpan = document.querySelector('#file-count');
const dropZone = document.querySelector('#drop-zone');
const output = document.querySelector('#output');
const previewContainer = document.querySelector('#preview-container');

// Helper: Format bytes to human-readable string
const formatFileSize = (bytes) => {
	if (bytes === 0) return '0 Bytes';
	const k = 1024;
	const sizes = ['Bytes', 'KB', 'MB', 'GB'];
	const i = Math.floor(Math.log(bytes) / Math.log(k));
	return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};

// Core Function: Process the FileList object
const handleFiles = (files) => {
	output.textContent = ''; // Clear previous log
	previewContainer.replaceChildren(); // Clear previews

	fileCountSpan.textContent = `${files.length} file(s) selected`;

	// The File API gives us a FileList, which is array-like but not an array.
	// We can convert it or loop standardly.
	Array.from(files).forEach((file) => {
		logMetadata(file);
		readFileContent(file);
	});
};

// 1. Inspect Metadata (Synchronous)
const logMetadata = (file) => {
	const logEntry = `
--- File Metadata ---
Name: ${file.name}
Type: ${file.type || 'Unknown'}
Size: ${formatFileSize(file.size)}
Last Modified: ${new Date(file.lastModified).toLocaleString()}
---------------------
`;
	output.textContent += logEntry;
};

// 2. Read Content (Asynchronous via FileReader)
const readFileContent = (file) => {
	const reader = new FileReader();

	// Setup Event Listeners BEFORE reading
	reader.onload = (event) => {
		// Success handler
		const result = event.target.result;

		// Logic to display content based on type
		if (file.type.startsWith('image/')) {
			const img = document.createElement('img');
			img.src = result; // The result is a Data URL (base64)
			img.classList.add('preview-thumb');
			previewContainer.appendChild(img);
			output.textContent += `\n[Image Preview Generated]\n`;
		} else if (
			file.type.startsWith('text/') ||
			file.type === 'application/json'
		) {
			// Truncate text for demo purposes if it's huge
			const previewText =
				result.length > 200 ? result.substring(0, 200) + '...' : result;
			output.textContent += `\nContent Preview:\n${previewText}\n`;
		}
	};

	reader.onerror = (error) => {
		console.error('Error reading file:', error);
		output.textContent += `\nError reading file: ${error.message}\n`;
	};

	// Trigger the read operation
	if (file.type.startsWith('image/')) {
		reader.readAsDataURL(file); // Great for previews
	} else {
		reader.readAsText(file); // Great for CSV, JSON, TXT
	}
};

// --- Event Listeners ---

// A. Standard Input Change
fileInput.addEventListener('change', (e) => {
	handleFiles(e.target.files);
});

// B. Drag and Drop "Gotchas"
// You MUST preventDefault on 'dragover' and 'drop' or the browser
// will open the file in the tab instead of letting JS handle it.

dropZone.addEventListener('dragover', (e) => {
	e.preventDefault();
	dropZone.classList.add('hover'); // Visual cue
});

dropZone.addEventListener('dragleave', () => {
	dropZone.classList.remove('hover');
});

dropZone.addEventListener('drop', (e) => {
	e.preventDefault();
	dropZone.classList.remove('hover');

	// Access the files via the dataTransfer object
	const files = e.dataTransfer.files;
	if (files.length > 0) {
		handleFiles(files);
	}
});

				
			

Takeaway

 If your app needs to import or preview user-selected files in the browser, the File API is where you start: FileListFile/Blob → read contents asynchronously (or synchronously in workers). It’s simple, widely useful, and the base layer for many “bring your own file” experiences on the web.

more posts:
Digital software technology development concept. Coder programmer, software engineer coding computer language, javascript on laptop computer
Code

An overview of the Fullscreen API

The Fullscreen API lets you display a specific element (and its descendants) in true fullscreen and then return to windowed mode. Learn the key methods, state checks, events, permissions considerations, and UX best practices for building focused video, game, and presentation experiences.

Discover More »