javascripthtmlfrontenddrag-and-dropfilesystems

FileEntry.file() method not working properly when opening an HTML file directly


I am working on a drag-and-drop upload feature. Through the drop event, I use e.dataTransfer.items to retrieve the handles for all files and folders, then call the items[n].webkitGetAsEntry() method to get the FileEntry object. Finally, I attempt to use the FileEntry.file((file) => {}) method to retrieve the file object from the callback:

function traverseFileTree(item, path = "") {
  // The item here is the return value of webkitGetAsEntry().
  const isRecursive = document.getElementById("recursiveOption").checked;
  if (item.isFile) {
    item.file(
      (file) => {
        console.log("file", file);
        if (file.name.toLowerCase().endsWith(".md")) {
          file.fullPath = path + file.name;
          files.push(file);
          updateFileList();
        }
      },
      (error) => {
        console.error(error);
        showPopup(`Failed to read file ${item.name}: ${error.message}`);
      }
    );
  } else if (item.isDirectory) {
    if (isRecursive || path === "") {
      let dirReader = item.createReader();
      dirReader.readEntries(
        (entries) => {
          for (let i = 0; i < entries.length; i++) {
            traverseFileTree(entries[i], path + item.name + "/");
          }
        },
        (error) => {
          console.error("Failed to read directory:", error);
          showPopup(`Failed to read directory ${item.name}: ${error.message}`);
        }
      );
    }
  }
}

However, something strange happens: when I open the HTML file directly in the browser (using the file protocol), the .file() method throws an EncodingError: file:

EncodingError: A URI supplied to the API was malformed, or the resulting Data URL has exceeded the URL length limitations for Data URLs.

But, when I serve the same HTML file through a local server (e.g., using Live Server over HTTP), the .file() method works as expected and I can successfully retrieve the file object. http:

I've searched various resources and consulted GPT but couldn't find a definitive answer. I suspect the issue may be related to browser security policies or relative path restrictions. Has anyone encountered this problem or knows what might be causing it?

I wish: Understand the specific cause of this issue. How should I solve similar problems on my own in the future?

Thank you!


Solution

  • The file:// protocol is severely limited in most browsers, Chrome especially. This is due to security concerns, though I could not find documentation on this specific problem (the error is also quite obtuse).

    The exact limitations depend on the API used, so try using a different one. For example, instead of dataTransferItem.webkitGetAsEntry() try dataTransferItem.getAsFile(), which gives you access to the file name (and size) even on file://.

    For drag-and-dropping directories on Chrome in file:// protocol, the only working alternative I found is the experimental dataTransferItem.getAsFileSystemHandle(). It gives you a richer set of options, including permissions.