What happens if you try to save a file with the same name in the same folder?

Want to get more out of Google Drive for work or school? Sign up for a Google Workspace trial at no charge. 

You can upload, view, share, and edit files with Google Drive. When you upload a file to Google Drive, it will take up space in your Drive, even if you upload to a folder owned by someone else.

Types of files

  • Documents
  • Images
  • Audio
  • Video

Upload files & folders

On your computer, you can upload from drive.google.com or your desktop. You can upload files into private or shared folders.

  1. On your computer, go to drive.google.com.
  2. At the top left, click New 
      File Upload or Folder Upload.
  3. Choose the file or folder you want to upload.

Drag files into Google Drive

  1. On your computer, go to drive.google.com.
  2. Open or create a folder.
  3. To upload files and folders, drag them into the Google Drive folder.

Use Drive for desktop

  1.  on your computer.
  2. On your computer, you'll see a folder called "Google Drive."
  3. Drag files or folders into that folder. They will upload to Drive and you will see them on drive.google.com.

Save from Print view 

Important: Make sure you have the Save to Google Drive Extension installed. 

  1. On your computer, open Chrome.
  2. Open the page, image, or file you want to print.
  3. On the top, click File
     Print.
  4. In the window, select Save to Drive or click See more 
     Save to Drive. 
  5. Click Print.

Convert documents into Google formats

If you want to upload files like Microsoft Word documents, you can change a setting to convert files.

Important: You can only change Google Drive settings from your computer.

  1. Using a computer, go to drive.google.com/drive/settings.
  2. Next to "Convert Uploads," check the box.

Upload files with the same name

If you upload a file with the same name, Google Drive will upload the file as a revision of the file already in Google Drive.

The File System Access API allows web apps to read or save changes directly to files and folders on the user's device.

Published on Tuesday, August 20, 2019 Updated on Wednesday, November 2, 2022

Pete LePage

Pete is a Developer Advocate

Thomas Steiner

Tom is a Developer Advocate

Table of contents

What is the File System Access API?

The File System Access API (formerly known as Native File System API and prior to that it was called Writeable Files API) enables developers to build powerful web apps that interact with files on the user's local device, such as IDEs, photo and video editors, text editors, and more. After a user grants a web app access, this API allows them to read or save changes directly to files and folders on the user's device. Beyond reading and writing files, the File System Access API provides the ability to open a directory and enumerate its contents.

The File System Access API—despite the similar name—is distinct from the let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});2 interface exposed by the , which documents the types and operations made available by browsers to script when a hierarchy of files and directories are dragged and dropped onto a page or selected using form elements or equivalent user actions.

It is likewise distinct from the deprecated File API: Directories and System specification, which defines an API to navigate file system hierarchies and a means by which browsers may expose sandboxed sections of a user's local filesystem to web applications.

If you've worked with reading and writing files before, much of what I'm about to share will be familiar to you. I encourage you to read it anyway, because not all systems are alike.

We've put a lot of thought into the design and implementation of the File System Access API to ensure that people can easily manage their files. See the section for more information.

The File System Access API is currently supported on most Chromium browsers on Windows, macOS, ChromeOS, and Linux. A notable exception is Brave where it is currently only available behind a flag. Android support is coming for the origin private file system part (//crbug.com/1354273). There are no plans currently for picker methods, but you can track potential progress by starring crbug.com/1011535.

Using the File System Access API

To show off the power and usefulness of the File System Access API, I wrote a single file text editor. It lets you open a text file, edit it, save the changes back to disk, or start a new file and save the changes to disk. It's nothing fancy, but provides enough to help you understand the concepts.

Try it

See the File System Access API in action in the text editor demo.

Read a file from the local file system

The first use case I want to tackle is to ask the user to choose a file, then open and read that file from disk.

Ask the user to pick a file to read

The entry point to the File System Access API is . When called, it shows a file picker dialog box, and prompts the user to select a file. After they select a file, the API returns an array of file handles. An optional let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});4 parameter lets you influence the behavior of the file picker, for example, by allowing the user to select multiple files, or directories, or different file types. Without any options specified, the file picker allows the user to select a single file. This is perfect for a text editor.

Like many other powerful APIs, calling let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});5 must be done in a secure context, and must be called from within a user gesture.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
// Destructure the one-element array.
[fileHandle] = await window.showOpenFilePicker();
// Do something with the file handle.
});

Once the user selects a file, let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});5 returns an array of handles, in this case a one-element array with one that contains the properties and methods needed to interact with the file.

It's helpful to keep a reference to the file handle so that it can be used later. It'll be needed to save changes to the file, or to perform any other file operations.

Read a file from the file system

Now that you have a handle to a file, you can get the file's properties, or access the file itself. For now, I'll simply read its contents. Calling let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});8 returns a let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});9 object, which contains a blob. To get the data from the blob, call one of its methods, (async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}0, async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}1, async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}2, or async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}3).

const file = await fileHandle.getFile();
const contents = await file.text();

For the majority of use cases, you can read files in sequential order with the async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}1, async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}2, or async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}3 methods. For getting random access to a file's contents, use the async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}0 method.

The let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});9 object returned by async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}9 is only readable as long as the underlying file on disk hasn't changed. If the file on disk is modified, the let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});9 object becomes unreadable and you'll need to call // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}1 again to get a new let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});9 object to read the changed data.

Putting it all together

When users click the Open button, the browser shows a file picker. Once they've selected a file, the app reads the contents and puts them into a // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}3.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});

Write the file to the local file system

In the text editor, there are two ways to save a file: Save, and Save As. Save simply writes the changes back to the original file using the file handle retrieved earlier. But Save As creates a new file, and thus requires a new file handle.

Create a new file

To save a file, call , which shows the file picker in "save" mode, allowing the user to pick a new file they want to use for saving. For the text editor, I also wanted it to automatically add a // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}5 extension, so I provided some additional parameters.

async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}

Gotchas

Sometimes processing the to-be-saved data takes some time after the user clicks the Save button in your app. A common gotcha is to do this work before the // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}4 code has run, resulting in a // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}7. Instead, get the file handle first, and only after obtaining the file handle start processing the data.

Save changes to disk

You can find all the code for saving changes to a file in my text editor demo on GitHub. The core file system interactions are in // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}8. At its simplest, the process looks like the code below. I'll walk through each step and explain it.

// fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}

Writing data to disk uses a object, a subclass of async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}0. Create the stream by calling async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}1 on the file handle object. When async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}1 is called, the browser first checks if the user has granted write permission to the file. If permission to write hasn't been granted, the browser prompts the user for permission. If permission isn't granted, async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}1 throws a async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}4, and the app will not be able to write to the file. In the text editor, the async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}4 objects are handled in the async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}6 method.

The async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}7 method takes a string, which is what's needed for a text editor. But it can also take a BufferSource, or a Blob. For example, you can pipe a stream directly to it:

async function writeURLToFile(fileHandle, url) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Make an HTTP request for the contents.
const response = await fetch(url);
// Stream the response into the file.
await response.body.pipeTo(writable);
// pipeTo() closes the destination pipe by default, no need to close it.
}

You can also , or within the stream to update the file at a specific position, or resize the file.

Caution

Changes are not written to disk until the stream is closed, either by calling const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});0 or when the stream is automatically closed by the pipe.

Specifying a suggested file name and start directory

In many cases you may want your app to suggest a default file name or location. For example, a text editor might want to suggest a default file name of const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});1 rather than const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});2. You can achieve this by passing a const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});3 property as part of the const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});4 options.

const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});

The same goes for the default start directory. If you're building a text editor, you may want to start the file save or file open dialog in the default const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});5 folder, whereas for an image editor, may want to start in the default const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});6 folder. You can suggest a default start directory by passing a const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});7 property to the const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});4, const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});9, or const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});0 methods like so.

const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});

The list of the well-known system directories is:

  • const fileHandle = await self.showOpenFilePicker({
    startIn: 'pictures'
    });1: The user's desktop directory, if such a thing exists.
  • const fileHandle = await self.showSaveFilePicker({
    suggestedName: 'Untitled Text.txt',
    types: [{
    description: 'Text documents',
    accept: {
    'text/plain': ['.txt'],
    },
    }],
    });5: Directory in which documents created by the user would typically be stored.
  • const fileHandle = await self.showOpenFilePicker({
    startIn: 'pictures'
    });3: Directory where downloaded files would typically be stored.
  • const fileHandle = await self.showOpenFilePicker({
    startIn: 'pictures'
    });4: Directory where audio files would typically be stored.
  • const fileHandle = await self.showSaveFilePicker({
    suggestedName: 'Untitled Text.txt',
    types: [{
    description: 'Text documents',
    accept: {
    'text/plain': ['.txt'],
    },
    }],
    });6: Directory where photos and other still images would typically be stored.
  • const fileHandle = await self.showOpenFilePicker({
    startIn: 'pictures'
    });6: Directory where videos/movies would typically be stored.

Apart from well-known system directories, you can also pass an existing file or directory handle as a value for const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});7. The dialog would then open in the same directory.

// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});

Specifying the purpose of different file pickers

Sometimes applications have different pickers for different purposes. For example, a rich text editor may allow the user to open text files, but also to import images. By default, each file picker would open at the last-remembered location. You can circumvent this by storing const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});8 values for each type of picker. If an const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});8 is specified, the file picker implementation remembers a separate last-used directory for that const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});8.

const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});

Storing file handles or directory handles in IndexedDB

File handles and directory handles are serializable, which means that you can save a file or directory handle to IndexedDB, or call // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});1 to send them between the same top-level origin.

Saving file or directory handles to IndexedDB means that you can store state, or remember which files or directories a user was working on. This makes it possible to keep a list of recently opened or edited files, offer to re-open the last file when the app is opened, restore the previous working directory, and more. In the text editor, I store a list of the five most recent files the user has opened, making it easy to access those files again.

The code example below shows storing and retrieving a file handle and a directory handle. You can see this in action over on Glitch. (I use the idb-keyval library for brevity.)

const file = await fileHandle.getFile();
const contents = await file.text();0

Stored file or directory handles and permissions

Since permissions currently are not persisted between sessions, you should verify whether the user has granted permission to the file or directory using // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});2. If they haven't, call // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});3 to (re-)request it. This works the same for file and directory handles. You need to run // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});4 or // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});5 respectively.

In the text editor, I created a // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});6 method that checks if the user has already granted permission, and if required, makes the request.

const file = await fileHandle.getFile();
const contents = await file.text();1

By requesting write permission with the read request, I reduced the number of permission prompts; the user sees one prompt when opening the file, and grants permission to both read and write to it.

While // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});7 objects can be , the permissions currently need to be re-granted each time, which is suboptimal. Star crbug.com/1011533 to be notified of work on persisting granted permissions.

Opening a directory and enumerating its contents

To enumerate all files in a directory, call . The user selects a directory in a picker, after which a is returned, which lets you enumerate and access the directory's files. By default, you will have read access to the files in the directory, but if you need write access, you can pass const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});0 to the method.

const file = await fileHandle.getFile();
const contents = await file.text();2

If you additionally need to access each file via // fileHandle is an instance of FileSystemFileHandle..
async function writeFile(fileHandle, contents) {
// Create a FileSystemWritableFileStream to write to.
const writable = await fileHandle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();
}1 to, for example, obtain the individual file sizes, do not use const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});2 on each result sequentially, but rather process all files in parallel, for example, via const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});3.

const file = await fileHandle.getFile();
const contents = await file.text();3

Creating or accessing files and folders in a directory

From a directory, you can create or access files and folders using the or respectively the method. By passing in an optional let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});4 object with a key of const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});7 and a boolean value of const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});8 or const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});9, you can determine if a new file or folder should be created if it doesn't exist.

const file = await fileHandle.getFile();
const contents = await file.text();4

Resolving the path of an item in a directory

When working with files or folders in a directory, it can be useful to resolve the path of the item in question. This can be done with the aptly named method. For resolving, the item can be a direct or indirect child of the directory.

const file = await fileHandle.getFile();
const contents = await file.text();5

Deleting files and folders in a directory

If you have obtained access to a directory, you can delete the contained files and folders with the method. For folders, deletion can optionally be recursive and include all subfolders and the files contained therein.

const file = await fileHandle.getFile();
const contents = await file.text();6

Deleting a file or folder directly

If you have access to a file or directory handle, call const file = await fileHandle.getFile();
const contents = await file.text();02 on a let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});7 or // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});9 to remove it.

const file = await fileHandle.getFile();
const contents = await file.text();7

The const file = await fileHandle.getFile();
const contents = await file.text();05 method is currently behind a flag.

Renaming and moving files and folders

Files and folders can be renamed or moved to a new location by calling const file = await fileHandle.getFile();
const contents = await file.text();06 on the // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});7 interface. // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});7 has the child interfaces let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});7 and // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});9. The const file = await fileHandle.getFile();
const contents = await file.text();06 method takes one or two parameters. The first can either be a string with the new name or a // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});9 to the destination folder. In the latter case, the optional second parameter is a string with the new name, so moving and renaming can happen in one step.

const file = await fileHandle.getFile();
const contents = await file.text();8

The const file = await fileHandle.getFile();
const contents = await file.text();13 method has shipped for files within the origin private file system (OPFS), is behind a flag for files if the source or destination is outside of the OPFS, and is not yet supported for directories.

Drag and drop integration

The HTML Drag and Drop interfaces enable web applications to accept dragged and dropped files on a web page. During a drag and drop operation, dragged file and directory items are associated with file entries and directory entries respectively. The const file = await fileHandle.getFile();
const contents = await file.text();14 method returns a promise with a let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});7 object if the dragged item is a file, and a promise with a // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});9 object if the dragged item is a directory. The listing below shows this in action. Note that the Drag and Drop interface's const file = await fileHandle.getFile();
const contents = await file.text();17 is const file = await fileHandle.getFile();
const contents = await file.text();18 for both files and directories, whereas the File System Access API's is const file = await fileHandle.getFile();
const contents = await file.text();18 for files and const file = await fileHandle.getFile();
const contents = await file.text();21 for directories.

const file = await fileHandle.getFile();
const contents = await file.text();9

Accessing the origin private file system

The origin private file system is a storage endpoint that, as the name suggests, is private to the origin of the page. While browsers typically implement this by persisting the contents of this origin private file system to disk somewhere, it is not intended that the contents be easily user accessible. Similarly, there is no expectation that files or directories with names matching the names of children of the origin private file system exist. While the browser might make it seem that there are files, internally—since this is an origin private file system—the browser might store these "files" in a database or any other data structure. Essentially, if you use this API, do not expect to find the created files matched one-to-one somewhere on the hard disk. You can operate as usual on the origin private file system once you have access to the root // Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});9.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});0

Accessing files optimized for performance from the origin private file system

The origin private file system provides optional access to a special kind of file that is highly optimized for performance, for example, by offering in-place and exclusive write access to a file's content. In Chromium 102 and later, there is an additional method on the origin private file system for simplifying file access: const file = await fileHandle.getFile();
const contents = await file.text();23 (for synchronous read and write operations). It is exposed on let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});7, but exclusively in Web Workers.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});1

People interested in the const file = await fileHandle.getFile();
const contents = await file.text();25 method (that is, the async variant available on the main thread and in Web Workers) should track crbug.com/1323922.

Polyfilling

It is not possible to completely polyfill the File System Access API methods.

  • The let fileHandle;
    butOpenFile.addEventListener('click', async () => {
    [fileHandle] = await window.showOpenFilePicker();
    const file = await fileHandle.getFile();
    const contents = await file.text();
    textArea.value = contents;
    });5 method can be approximated with an const file = await fileHandle.getFile();
    const contents = await file.text();27 element.
  • The // fileHandle is an instance of FileSystemFileHandle..
    async function writeFile(fileHandle, contents) {
    // Create a FileSystemWritableFileStream to write to.
    const writable = await fileHandle.createWritable();
    // Write the contents of the file to the stream.
    await writable.write(contents);
    // Close the file and write the contents to disk.
    await writable.close();
    }4 method can be simulated with a const file = await fileHandle.getFile();
    const contents = await file.text();29 element, albeit this triggers a programmatic download and not allow for overwriting existing files.
  • The const fileHandle = await self.showSaveFilePicker({
    suggestedName: 'Untitled Text.txt',
    types: [{
    description: 'Text documents',
    accept: {
    'text/plain': ['.txt'],
    },
    }],
    });9 method can be somewhat emulated with the non-standard const file = await fileHandle.getFile();
    const contents = await file.text();31 element.

We have developed a library called browser-fs-access that uses the File System Access API wherever possible and that falls back to these next best options in all other cases.

Security and permissions

The Chrome team has designed and implemented the File System Access API using the core principles defined in Controlling Access to Powerful Web Platform Features, including user control and transparency, and user ergonomics.

Opening a file or saving a new file

A file picker used to open an existing file for reading.

When opening a file, the user provides permission to read a file or directory via the file picker. The open file picker can only be shown via a user gesture when served from a secure context. If users change their minds, they can cancel the selection in the file picker and the site does not get access to anything. This is the same behavior as that of the const file = await fileHandle.getFile();
const contents = await file.text();27 element.

A file picker used to save a file to disk.

Similarly, when a web app wants to save a new file, the browser shows the save file picker, allowing the user to specify the name and location of the new file. Since they are saving a new file to the device (versus overwriting an existing file), the file picker grants the app permission to write to the file.

Restricted folders

To help protect users and their data, the browser may limit the user's ability to save to certain folders, for example, core operating system folders like Windows, the macOS Library folders, etc. When this happens, the browser shows a modal prompt and ask the user to choose a different folder.

Modifying an existing file or directory

A web app cannot modify a file on disk without getting explicit permission from the user.

Permission prompt

If a person wants to save changes to a file that they previously granted read access to, the browser shows a modal permission prompt, requesting permission for the site to write changes to disk. The permission request can only be triggered by a user gesture, for example, by clicking a Save button.

Prompt shown to users before the browser is granted write permission on an existing file.

Alternatively, a web app that edits multiple files, such as an IDE, can also ask for permission to save changes at the time of opening.

If the user chooses Cancel, and does not grant write access, the web app cannot save changes to the local file. It should provide an alternative method for the user to save their data, for example by providing a way to "download" the file, saving data to the cloud, etc.

Transparency

Omnibox icon indicating the user has granted the website permission to save to a local file.

Once a user has granted permission to a web app to save a local file, the browser shows an icon in the URL bar. Clicking on the icon opens a pop-over showing the list of files the user has given access to. The user can easily revoke that access if they choose.

Permission persistence

The web app can continue to save changes to the file without prompting until all tabs for its origin are closed. Once a tab is closed, the site loses all access. The next time the user uses the web app, they will be re-prompted for access to the files.

Feedback

We want to hear about your experiences with the File System Access API.

Tell us about the API design

Is there something about the API that doesn't work like you expected? Or are there missing methods or properties that you need to implement your idea? Have a question or comment on the security model?

  • File a spec issue on the WICG File System Access GitHub repo, or add your thoughts to an existing issue.

Problem with the implementation?

Did you find a bug with Chrome's implementation? Or is the implementation different from the spec?

  • File a bug at //new.crbug.com. Be sure to include as much detail as you can, simple instructions for reproducing, and set Components to const file = await fileHandle.getFile();
    const contents = await file.text();33. Glitch works great for sharing quick and easy repros.

Planning to use the API?

Planning to use the File System Access API on your site? Your public support helps us to prioritize features, and shows other browser vendors how critical it is to support them.

What happens if two files have the same name?

A filename (or file name) is used to identify a storage location in the file system. OS wants unique file names because when you will tell OS to do something, and you have two files with exactly the same name, OS can't know which file to perform the action on.

Can we have two files by the same name in the same folder?

Answer. Answer: In environments in which a file is named, a file's name and the path to the file's directory must uniquely identify it among all other files in the computer system—no two files can have the same name and path.

Can a folder contain many files with the same name?

Expert-Verified Answer In the very same folder, there cannot be two files with the same name. Either you must save every user's documents in a folder assigned to their account, as you suggest, or you would have to append a random string to the end of each file.

How it is possible for two files with the same name to be stored in a file structure?

You cannot have two files with the same name in the same folder. You would either have to add a random string to the end of each file like you suggest or save each user's files in a directory allocated to their account. Save this answer.

Toplist

Neuester Beitrag

Stichworte