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
How to Open a Business Bank Account
What is Interperiod Tax Allocation?
Joy Ride movie review & film summary (2023) | Roger Ebert
Cars for Sale by Owner in Shreveport, LA
Seething Storm
SCDOR | Sales Tax
Netronline Historic Aerials
SUN WOOD ➠ the ultimate alternative to reclaimed wood & precious wood
Lohikeitto (Finnish Salmon Soup) Recipe on Food52
Poke Bowl Hawaïen Traditionnel : Frais, Sain et Délicieux
Restored Republic June 6 2023
Text Dollar To 58046
Kreamlatifah
Naughty Nails Southern Charms
How To Breed A Loot Dragon In Dragonvale
Fish Counts - Sport Fish
Saybyebugs At Walmart
Madness Combat Wiki
Printable Coupon $3 Off Pull-Ups
New Jersey Cash Pop
Erica Mena Net Worth Forbes
Equipment Hypixel Skyblock
Walgreens Launches 24-Hour Same Day Delivery, Offering the Most Retail Items for Around the Clock Delivery Across the Country
Different Types of Nameplates, Nameplate Materials & More
Rubmaps Chicago
Craigslist Pets Gainesville Fl
Deep Rock Galactic How to Level Up Fast
How Sonny and Cher Went From TV's Power Couple to Bitter Exes
Sign of the times: Emma Memma finds her calling after Wiggles
Houses For Sale 180 000
How Did Natalie Earnheart Lose Weight
Standard Bank Learnership Programme 2021
Courier Press Sports
Olivia Dunne says 'tears filled my eyes' as LSU won NCAA women's gymnastics championship
Kreme Delite Menu
Student Doctor Network Anesthesia
Carly Hart Playboy
Farosh's Horn Botw
Www Https Retirees Aa Com
M12 X 1.5 : Thread Dimensions (Machining Doctor)
Instagram - Brianna Aerial
Hyundai Scottsdale
What is 802.11n? | Definition from TechTarget
Rondale Moore Or Gabe Davis
Neos Urgent Care Springfield Ma
Busted Newspaper Kershaw County
Sharp Charts
Hexanaut.io Unblocked
Restored Republic Jan 3 2023
Costco Members: Any Set of 4 Michelin Tires $200 Off $900+
Metro Pcs Locations Near Me
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.