showOpenFilePicker: A Complete Guide to the Modern File Picker API

Enable native file selection in your web applications with the File System Access API. Learn to implement persistent file handles, direct file writing, and progressive enhancement patterns.

What is showOpenFilePicker?

The showOpenFilePicker() method is part of the File System Access API, a modern web platform feature that enables web applications to interact with files stored on a user's local device. When called, this method displays the operating system's native file picker dialog, allowing users to select one or more files from their file system. Upon successful selection, the method returns a Promise that resolves to an array of FileSystemFileHandle objects.

Unlike the traditional <input type="file"> approach, showOpenFilePicker() provides persistent file handles rather than one-time file uploads. A FileSystemFileHandle is an object that represents a file and provides methods for reading its contents and, importantly, writing changes directly back to the original file.

This API is particularly valuable for applications that work with user-generated content. Document editors can let users open their existing files and save modifications directly. Image editing applications can read source files and write processed results. Data visualization tools can import datasets and export modified versions.

Key Capabilities

  • Opening single or multiple files through a consistent interface
  • Filtering file types to guide user selections
  • Persisting file handles for repeated access
  • Reading file contents efficiently without server uploads
  • Writing changes directly to selected files
  • Remembering user preferences for future sessions

The File System Access API represents a significant advancement in modern web development, enabling applications to interact with local files directly through the browser. Unlike traditional approaches that require file uploads and downloads, this native browser API allows users to open files from their device and save changes directly back to the original file.

Syntax and Parameters

Configure the file picker with flexible options

Basic Syntax

Simple API that returns a Promise resolving to an array of FileSystemFileHandle objects

Multiple Selection

Enable multi-file selection with the `multiple: true` option

File Type Filters

Guide users with MIME type and extension filters in the picker UI

Starting Directory

Specify initial directory with `startIn` option using well-known paths

ID Persistence

Remember picker state across sessions with the `id` parameter

Strict Filtering

Hide "all files" option with `excludeAcceptAllOption`

Basic Single File Selection
1// Basic single file selection2const [handle] = await window.showOpenFilePicker();3 4// Get file object for reading5const file = await handle.getFile();6console.log(file.name); // Original filename7console.log(file.size); // File size in bytes8console.log(file.type); // MIME type9 10// Read file contents11const text = await file.text();12const buffer = await file.arrayBuffer();
Multiple File Selection with Type Filters
1// Multiple file selection with type filters2const handles = await showOpenFilePicker({3 multiple: true,4 types: [5 {6 description: 'Image files',7 accept: {8 'image/png': ['.png'],9 'image/jpeg': ['.jpg', '.jpeg'],10 'image/gif': ['.gif'],11 'image/webp': ['.webp']12 }13 },14 {15 description: 'Documents',16 accept: {17 'application/pdf': ['.pdf'],18 'application/msword': ['.doc'],19 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx']20 }21 }22 ],23 excludeAcceptAllOption: true24});25 26// Process each selected file27for (const handle of handles) {28 const file = await handle.getFile();29 console.log(`Processing: ${file.name}`);30}
Writing Changes Directly to Files
1// Writing changes directly to the original file2const [handle] = await showOpenFilePicker({3 types: [{ description: 'Text files', accept: { 'text/plain': ['.txt'] } }]4});5 6// Create a writable stream7const writable = await handle.createWritable();8 9// Write content10await writable.write('New content for the file');11 12// Close the stream to finalize the write13await writable.close();14 15// The file is now updated on disk!

Browser Compatibility

The showOpenFilePicker() method has limited browser support, which is a critical consideration when deciding whether to use this API.

Current Browser Support

BrowserVersionSupport
Chrome86+Full Support
Edge86+Full Support
FirefoxNot SupportedNo Support
SafariNot SupportedNo Support

Chrome version 86 and later fully supports the File System Access API. Microsoft Edge also supports the API starting from version 86, as it is based on Chromium. Firefox and Safari do not currently support this API.

Feature Detection

Proper feature detection is essential:

function supportsFileSystemAccess() {
 return 'showOpenFilePicker' in window &&
 window.self === window.top;
}

This check verifies that the method exists on the Window object and that the page is not running inside an iframe, which would prevent the API from functioning even in supporting browsers.

Progressive Enhancement Strategy

The recommended strategy is progressive enhancement: use the File System Access API when supported, but fall back to traditional file input for unsupported browsers. This approach provides the best possible experience for users with modern browsers while maintaining functionality for all users.

async function openFiles(multiple = false) {
 // Check for File System Access API support
 if ('showOpenFilePicker' in window && window.self === window.top) {
 try {
 const handles = await showOpenFilePicker({ multiple });
 return handles.map(handle => ({
 handle,
 file: await handle.getFile()
 }));
 } catch (error) {
 if (error.name !== 'AbortError') {
 console.error('File picker error:', error);
 }
 return null;
 }
 }

 // Fallback to traditional file input
 return new Promise((resolve) => {
 const input = document.createElement('input');
 input.type = 'file';
 input.multiple = multiple;
 input.style.display = 'none';
 document.body.appendChild(input);

 input.addEventListener('change', () => {
 input.remove();
 const files = multiple ? Array.from(input.files) : input.files[0];
 resolve(files);
 });

 input.click();
 });
}

This pattern ensures that all users can select files, though those using browsers without File System Access API support will experience the traditional upload workflow rather than direct file access. For applications requiring broader compatibility, consider implementing this fallback strategy as part of your web application development approach.

Security Requirements

The File System Access API implements multiple security layers to protect users while enabling useful functionality.

Secure Context Requirement

The showOpenFilePicker() method is only available in secure contexts, which means the page must be served over HTTPS or loaded from localhost. This requirement prevents sensitive file operations from occurring over unencrypted connections where data could be intercepted.

User Activation

The API requires user activation, meaning it must be called in response to a user gesture such as a button click or form submission:

// This works - triggered by user click
document.getElementById('openButton').addEventListener('click', async () => {
 const [handle] = await showOpenFilePicker();
});

// This fails - no user activation
const handles = await showOpenFilePicker(); // Error!

Permission Model

While the initial file selection is controlled by the native file picker UI, subsequent access to file handles requires appropriate permissions. The browser manages these permissions based on user actions and may prompt for confirmation.

Error Types

  • AbortError: User cancelled the file picker (normal, handle gracefully)
  • SecurityError: API used outside secure context or without user activation
  • TypeError: Invalid options object parameters

Understanding these security requirements is essential for building secure JavaScript applications that handle files safely.

Best Practices and Performance

Streaming Large Files

For large files, use streaming approaches rather than loading entire contents into memory:

const [handle] = await showOpenFilePicker();
const file = await handle.getFile();

// Use streams for large files
const stream = file.stream();
const reader = stream.getReader();

while (true) {
 const { done, value } = await reader.read();
 if (done) break;
 // Process chunk: value is a Uint8Array
 processChunk(value);
}

Caching File Handles

Store handles for frequently accessed files rather than asking users to reselect them.

User Experience Guidelines

  • Clear Labels: Use descriptive button text like "Open Document" instead of just "Open"
  • Show File Previews: Display information about selected files after selection
  • Provide Feedback: Show loading states during file operations, especially for large files

Comparison with Traditional File Input

AspectTraditional InputshowOpenFilePicker
Access typeOne-time snapshotPersistent handle
Save methodServer upload or downloadDirect file write
File typesLimited filteringRich type specification
User experienceGeneric pickerConfigurable starting location
Offline capabilityRequires uploadFull offline support
Large filesMemory intensiveStreaming support

When to Use Each Approach

Choose showOpenFilePicker() when:

  • Building document or media editing applications
  • Processing files entirely client-side
  • Users need to modify and save original files
  • Persistent file access improves workflow
  • Large file handling is required

Choose traditional file input when:

  • Targeting maximum browser compatibility
  • File processing happens server-side
  • Simple upload workflows are sufficient
  • Progressive enhancement is not feasible
  • Minimal implementation complexity is desired

For applications that benefit from direct file access, the File System Access API provides capabilities that were previously only available in native applications. This is particularly valuable for custom software solutions that require sophisticated file handling workflows. To learn more about building powerful client-side applications, explore our web development expertise.

Frequently Asked Questions

Ready to Build Modern Web Applications?

Our team specializes in leveraging modern web APIs to create powerful, user-friendly applications that rival native experiences. Contact us to discuss your project.

Sources

  1. MDN Web Docs - Window.showOpenFilePicker() - Official API reference documentation
  2. Chrome for Developers - File System Access API - Google's official implementation guide
  3. web.dev - Open One or Multiple Files Pattern - Progressive enhancement patterns