file-uploadhtml5-filesystemnative-file-system-api-js

FileSystemApi and writableStream


I'm trying to use the FileSystem API to write an uploaded file on a SPA to a Local sandboxed FileSystem using the FileSystem API.

The File Is uploaded with drop acion and I can get the File object array in the call back. From the File I can get the ReadableStream calling the stream method (yes, it return only readable sream).

Considering that the uploaded file could be big enough, I would go for a streaming than loading entirely into a blob and then writing into FileSystem api.

So, following the docs the steps are:

  1. get a FileSystem (DOMFileSystem) through the async webkitRequestFileSystem call.
  2. get the prop root that is a FileSystemDirectoryEntry
  3. create a file through getFile (with flag create:true) that returns (async) a FileSystemFileEntry

Now from the FileEntry I can get a FileWriter using createWriter but it is obsolete (in MDN), and in any case it is a FileWriter while I would look to obtain a WritableStream instead in order to use the pipeTo from the uploaded file Handler->ReadableStream.

So, I see that in the console the class (interface) FileSystemFileHandler is defined but I cannot understand how to get an instance from the FileSystemFileEntry. If I can obtain a FileSystemFileHandler I can call the createWritable to obtain a FileSystemWritableFileStream that I can "pipe" with the ReadStream.

Anyone who can clarify this mess ?

references: https://web.dev/file-system-access/ https://wicg.github.io/file-system-access/#filesystemhandle https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry


Solution

  • You have the solution in your "references" links at the bottom. Specifically, this is the section to read. You can create files or directories like so:

    // In an existing directory, create a new directory named "My Documents".
    const newDirectoryHandle = await existingDirectoryHandle.getDirectoryHandle('My Documents', {
      create: true,
    });
    // In this new directory, create a file named "My Notes.txt".
    const newFileHandle = await newDirectoryHandle.getFileHandle('My Notes.txt', { create: true });
    

    Once you have a file handle, you can then pipe to it or write to it:

    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();
    }
    

    …or…

    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.
    }