How to open a directory  |  Files and directories patterns  |  web.dev (2024)

  • Home
  • Patterns
  • Files and directories patterns
Stay organized with collections Save and categorize content based on your preferences.

Dealing with directories is not something you will cope with on a daily basis,but occasionally the use case arises, such as wanting to process all images in a directory.With the File System Access API, users can now open directories in the browserand decide if they need write access or not.

The modern way

Using the File System Access API's showDirectoryPicker() method

To open a directory, callshowDirectoryPicker(),which returns a promise with the picked directory. If you need write access, you can pass { mode: 'readwrite' } to the method.

Browser Support

  • How to open a directory | Files and directories patterns | web.dev (4) 86
  • How to open a directory | Files and directories patterns | web.dev (5) 86
  • How to open a directory | Files and directories patterns | web.dev (6) x
  • How to open a directory | Files and directories patterns | web.dev (7) x

Source

The classic way

Using the <input type="file" webkitdirectory> element

The <input type="file" webkitdirectory> element on a page allows the user to click it and opena directory. The trick now consists of inserting the element invisibly into a page with JavaScript and click it programmatically.

Browser Support

  • How to open a directory | Files and directories patterns | web.dev (8) 7
  • How to open a directory | Files and directories patterns | web.dev (9) 13
  • How to open a directory | Files and directories patterns | web.dev (10) 50
  • How to open a directory | Files and directories patterns | web.dev (11) 11.1

Source

Progressive enhancement

The method below uses the File System Access API when it's supportedand else falls back to the classic approach. In both cases the functionreturns a directory, but in case of where the File System Access APIis supported, each file object also has a FileSystemDirectoryHandle stored inthe directoryHandle property and a FileSystemFileHandle stored in the handle property,so you can optionally serialize the handles to disk.

const openDirectory = async (mode = "read") => { // Feature detection. The API needs to be supported // and the app not run in an iframe. const supportsFileSystemAccess = "showDirectoryPicker" in window && (() => { try { return window.self === window.top; } catch { return false; } })(); // If the File System Access API is supported… if (supportsFileSystemAccess) { let directoryStructure = undefined; // Recursive function that walks the directory structure. const getFiles = async (dirHandle, path = dirHandle.name) => { const dirs = []; const files = []; for await (const entry of dirHandle.values()) { const nestedPath = `${path}/${entry.name}`; if (entry.kind === "file") { files.push( entry.getFile().then((file) => { file.directoryHandle = dirHandle; file.handle = entry; return Object.defineProperty(file, "webkitRelativePath", { configurable: true, enumerable: true, get: () => nestedPath, }); }) ); } else if (entry.kind === "directory") { dirs.push(getFiles(entry, nestedPath)); } } return [ ...(await Promise.all(dirs)).flat(), ...(await Promise.all(files)), ]; }; try { // Open the directory. const handle = await showDirectoryPicker({ mode, }); // Get the directory structure. directoryStructure = getFiles(handle, undefined); } catch (err) { if (err.name !== "AbortError") { console.error(err.name, err.message); } } return directoryStructure; } // Fallback if the File System Access API is not supported. return new Promise((resolve) => { const input = document.createElement('input'); input.type = 'file'; input.webkitdirectory = true; input.addEventListener('change', () => { let files = Array.from(input.files); resolve(files); }); if ('showPicker' in HTMLInputElement.prototype) { input.showPicker(); } else { input.click(); } });};

Further reading

  • File System Access API

Demo

HTML

<!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📂</text></svg>" /> <title>How to open a directory</title> </head> <body> <h1>How to open a directory</h1> <button type="button">Open directory</button> <pre></pre> </body></html>

CSS

 :root { color-scheme: dark light;}html { box-sizing: border-box;}*,*:before,*:after { box-sizing: inherit;}body { margin: 1rem; font-family: system-ui, sans-serif;} 

JS

 const button = document.querySelector('button');const pre = document.querySelector('pre');const openDirectory = async (mode = "read") => { // Feature detection. The API needs to be supported // and the app not run in an iframe. const supportsFileSystemAccess = "showDirectoryPicker" in window && (() => { try { return window.self === window.top; } catch { return false; } })(); // If the File System Access API is supported… if (supportsFileSystemAccess) { let directoryStructure = undefined; const getFiles = async (dirHandle, path = dirHandle.name) => { const dirs = []; const files = []; for await (const entry of dirHandle.values()) { const nestedPath = `${path}/${entry.name}`; if (entry.kind === "file") { files.push( entry.getFile().then((file) => { file.directoryHandle = dirHandle; file.handle = entry; return Object.defineProperty(file, "webkitRelativePath", { configurable: true, enumerable: true, get: () => nestedPath, }); }) ); } else if (entry.kind === "directory") { dirs.push(getFiles(entry, nestedPath)); } } return [ ...(await Promise.all(dirs)).flat(), ...(await Promise.all(files)), ]; }; try { const handle = await showDirectoryPicker({ mode, }); directoryStructure = getFiles(handle, undefined); } catch (err) { if (err.name !== "AbortError") { console.error(err.name, err.message); } } return directoryStructure; } // Fallback if the File System Access API is not supported. return new Promise((resolve) => { const input = document.createElement('input'); input.type = 'file'; input.webkitdirectory = true; input.addEventListener('change', () => { let files = Array.from(input.files); resolve(files); }); if ('showPicker' in HTMLInputElement.prototype) { input.showPicker(); } else { input.click(); } });};button.addEventListener('click', async () => { const filesInDirectory = await openDirectory(); if (!filesInDirectory) { return; } Array.from(filesInDirectory).forEach((file) => (pre.textContent += `${file.name}\n`));}); 

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2024-09-17 UTC.

How to open a directory  |  Files and directories patterns  |  web.dev (2024)
Top Articles
Plus500 Pro | Apply to become a Professional Trader
EUR/INR Forecast & Price Prediction for 2024, 2025–2026 and Beyond | LiteFinance
Ach Credit Ftb Mct
Fantasy Football Week 3: 5 players who could make or break your lineups
Heccymar Salerno Video
Ultra Clear Epoxy Instructions
Clafi Arab
Linkbuilding Specialist Amsterdam
Comenity Bank Ann Taylor Loft
Washington 2024 UHC Dual Complete WA-D002 (HMO-POS D-SNP) Find a provider or pharmacy
Houston Ts Reviews
7206990815
Max Tl Nails
Guilford County Mugshots Zone
Bella Fiona Ristorante Menu
Transcripts - University of Phoenix
Vermont Free Stuff Craigslist
Huffington Post Scorpio Horoscope
Infinite Campus Farmingdale
The Miami Herald from Miami, Florida
Safelite Paris Tn
همسریابی دو همدم
Lubbock Avalanche Journal Newspaper Obituaries
Hwy 57 Nursery Michie Tn
Mady Gio Feet
Walkthrough - Summertime Saga Wiki
A Comprehensive Breakdown of All the Drama Between TikTok's Jack Wright and Sienna Mae - E! Online
Sales & Deals — My Nintendo Store - Nintendo Official Site
Swgoh Darth Malgus
Former Woodland Hills football standout dies in Larimer shooting
What Is Preggophilia — Make Personality
Vip Market Vetsource
Violent Night Showtimes Near Johnstown Movieplex
Tuscaloosa Mugshots Arrests
Rhian Sugden Forum
Craigslist Eastern Montana Farm And Garden
Lanna Crabtree
Ncaaf Reference
Ups Drop Close To Me
Hyvee Workday
Blower Motor Resistor Autozone
Busted Mugshots Paducah Ky
He bought a cruise ship on Craigslist and spent over $1 million restoring it. Then his dream sank
That Is No Sword Tanjiro X Kakushi
10Am Pt To London Time
Belk Employee Handbook 2022
Hca Scheduler Login
Craigslist Portland Oregon Motorcycles
Vera Bradley Factory Outlet Sunbury Photos
Dallas Cowboys On Sirius Xm Radio
Myhr North Memorial
E-Pedal And E-Step Systems Will Not Function When ______.
Latest Posts
Article information

Author: Edwin Metz

Last Updated:

Views: 6084

Rating: 4.8 / 5 (58 voted)

Reviews: 89% of readers found this page helpful

Author information

Name: Edwin Metz

Birthday: 1997-04-16

Address: 51593 Leanne Light, Kuphalmouth, DE 50012-5183

Phone: +639107620957

Job: Corporate Banking Technician

Hobby: Reading, scrapbook, role-playing games, Fishing, Fishing, Scuba diving, Beekeeping

Introduction: My name is Edwin Metz, I am a fair, energetic, helpful, brave, outstanding, nice, helpful person who loves writing and wants to share my knowledge and understanding with you.