You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在浏览器JavaScript中实现类似vscode.dev的用户授权式文件读写功能

Implementing File System Access with User Authorization (Like vscode.dev)

Hey there! The functionality you're aiming for is totally achievable using the File System Access API—this is exactly what tools like vscode.dev rely on to enable cross-platform file operations with user consent. Let’s walk through how to fill in your placeholder functions and get this working properly.

Key Background

Unlike some other APIs, the File System Access API doesn’t use a separate "permission request" dialog. Instead, consent is granted implicitly when the user selects a file or directory via the API’s picker methods. We’ll need to store the selected directory handle to perform all subsequent file operations.

Updated Working Code

Here’s your modified HTML framework with fully implemented functions using the File System Access API:

<!DOCTYPE html>
<html>
<head>
<title>File permission web</title>
<script>
// Store the selected directory handle for reuse across functions
let directoryHandle;

// Request access to a directory (this is your permission flow)
const reqPerm = async () => {
  try {
    // Prompt user to select a directory, requesting read/write access upfront
    directoryHandle = await window.showDirectoryPicker({
      mode: 'readwrite'
    });
    alert('Permission granted! You can now manage files in the selected directory.');
  } catch (err) {
    // Handle user cancellation or errors
    console.error('Permission denied or error:', err);
    alert('Permission denied or an error occurred.');
  }
};

// Create a new file in the selected directory
const createFile = async (fileName) => {
  if (!directoryHandle) {
    alert('Please grant directory access first!');
    return;
  }
  try {
    // Create or overwrite the file if it exists
    const fileHandle = await directoryHandle.getFileHandle(fileName, { create: true });
    // Open a writable stream and write empty initial content
    const writable = await fileHandle.createWritable();
    await writable.write('');
    await writable.close();
    alert(`Successfully created ${fileName}!`);
  } catch (err) {
    console.error('Error creating file:', err);
    alert('Failed to create the file.');
  }
};

// Delete a file from the selected directory
const deleteFile = async (fileName) => {
  if (!directoryHandle) {
    alert('Please grant directory access first!');
    return;
  }
  try {
    // Remove the file from the directory
    await directoryHandle.removeEntry(fileName);
    alert(`Successfully deleted ${fileName}!`);
  } catch (err) {
    console.error('Error deleting file:', err);
    alert('Failed to delete the file (it may not exist).');
  }
};

// Edit content of an existing file
const editFile = async (fileName, content) => {
  if (!directoryHandle) {
    alert('Please grant directory access first!');
    return;
  }
  try {
    const fileHandle = await directoryHandle.getFileHandle(fileName);
    const writable = await fileHandle.createWritable();
    // Overwrite existing content with the new value
    await writable.write(content);
    await writable.close();
    alert(`Successfully updated ${fileName}!`);
  } catch (err) {
    console.error('Error editing file:', err);
    alert('Failed to edit the file (it may not exist).');
  }
};

// View content of an existing file
const viewFile = async (fileName) => {
  if (!directoryHandle) {
    alert('Please grant directory access first!');
    return;
  }
  try {
    const fileHandle = await directoryHandle.getFileHandle(fileName);
    const file = await fileHandle.getFile();
    const content = await file.text();
    alert(`Content of ${fileName}:\n\n${content}`);
  } catch (err) {
    console.error('Error viewing file:', err);
    alert('Failed to view the file (it may not exist).');
  }
};
</script>
</head>
<body>
<center>
<h1>File permission</h1>
</br>
<button onclick="reqPerm()">Get permission (Select Directory)</button>
</br>
<button onclick="createFile('hello.txt')">Create hello.txt</button>
</br>
<button onclick="deleteFile('hello.txt')">Delete hello.txt</button>
</br>
<button onclick="editFile('hello.txt', 'hellomg')">Edit hello.txt</button>
</br>
<button onclick="viewFile('hello.txt')">View hello.txt</button>
</center>
</body>
</html>

Key Details to Know

  • Relative Paths: All file operations work relative to the directory the user selects—you don’t need full system paths anymore (like /home/runner/renne/hello.txt), just the file name.
  • Persistence Across Sessions: To retain access when the user reloads the page, you can save the directory handle to IndexedDB. Add this snippet to your script:
    // Save handle to IndexedDB
    const saveHandle = async () => {
      if (!directoryHandle) return;
      await navigator.storage.persist();
      const db = await indexedDB.open('FileAccessDB', 1);
      db.onupgradeneeded = () => db.createObjectStore('handles');
      const tx = db.transaction('handles', 'readwrite');
      tx.objectStore('handles').put(directoryHandle, 'selectedDir');
      await tx.complete();
    };
    
    // Load handle on page load
    window.addEventListener('load', async () => {
      const db = await indexedDB.open('FileAccessDB', 1);
      const tx = db.transaction('handles', 'readonly');
      const storedHandle = await tx.objectStore('handles').get('selectedDir');
      if (storedHandle) {
        // Verify permission is still granted
        const permission = await storedHandle.requestPermission({ mode: 'readwrite' });
        if (permission === 'granted') {
          directoryHandle = storedHandle;
          alert('Restored access to your previously selected directory!');
        }
      }
    });
    
  • Compatibility: This API works in all Chromium-based browsers (Chrome, Edge, Brave) across Windows, macOS, Linux, and Chromebooks—matching vscode.dev’s support.

Critical Restrictions

  • User Gesture Required: Calls to showDirectoryPicker() must be triggered by a user action (like clicking a button). Browsers block automatic requests for security.
  • Sandboxed Access: You can only interact with files/directories the user explicitly selects—no arbitrary system path access without consent.

内容的提问来源于stack exchange,提问作者iRennegade

火山引擎 最新活动