FileSystemFileEntry 的方法“file()”在本地文件上失败

问题描述 投票:0回答:1

我正在尝试同时使用 File 和 Drag'n'Drop API,特别是 webkitGetAsEntry 方法。从链接页面上的示例源代码中,您可能会找到指向 Mozilla 游乐场的更多链接(要共享到特定游乐场的直接链接,用户必须登录,所以我无法提供它,对于给您带来的不便,深表歉意)。

我唯一想添加到代码中的是读取放置在目标上的文件内容。所以我在 JS 代码中添加了以下内容:

function scanFiles(item, container) {
  let elem = document.createElement("li");
  elem.textContent = item.name;
  container.appendChild(elem);
  item.file((file) => {             // +
    fr = new FileReader();          // +
    fr.onload = function (e) {      // +
      console.log(e.target.result); // +
    };                              // +
    fr.readAsText(file);            // +
  }, (e) => console.log(e));        // +
  ...
}

该代码片段在 Web 服务器上正常工作(如果很重要,我使用一个小的测试 json 文件)。但是,当我尝试将文件拖放到本地 html 页面(带有片段的完整副本)时,方法

file()
失败并出现错误:

“DOMException:提供给 API 的 URI 格式错误,或者生成的数据 URL 超出了数据 URL 的 URL 长度限制。”

我不确定该项目的现有属性中哪个 URI 格式错误(取自调试器下的手表):

文件系统:DOMFileSystem {名称:'file__0:Isolated_2593BD5520A6B3C40C2DE438E8C2F58C',根:DirectoryEntry}
完整路径:“/small.json”
是目录:假
是文件: true
名称:“小.json”

无论如何,我不会手动输入任何URI,所有数据都是由浏览器本身获取和形成的。最重要的是 - 我没有找到编辑 URI 的方法(出于安全考虑,它已从文件 API 中删除)。

在本地托管的网页/网络应用程序中读取文件有什么问题?如何让它发挥作用?

据我所知,拖放 API 不适用 CORS 限制,而 FileSystem API 的设计目的是用于本地文件。

我用于测试的浏览器是 Brave。

PS。我已在浏览器设置中启用了文件系统访问 API,并且像 TiddlyStow 这样的本地应用程序似乎可以使用本地文件(尽管我不知道它到底应该如何工作)。

javascript fileapi
1个回答
0
投票

我找到了解决办法。应使用

webkitGetAsEntry()
代替
getAsFileSystemHandle()
方法。根据文档,两种方法都返回
FileSystemEntry
对象,但第一个方法施加了一些安全限制,而第二个方法则没有。第二个也包含在一个承诺中,并标记为实验性的。

这是源代码,其中有注释指出的更改。

async function scanFiles(item, container) {              //+ async
  let elem = document.createElement("li");
  elem.textContent = item.name;
  container.appendChild(elem);
  if(item.kind === 'file') {
    const file = await item.getFile();
    let data = document.createElement("div");
    data.innerHTML = "";
    container.appendChild(data);
    fr = new FileReader();
    fr.onload = function (e) {
      let lines = e.target.result;
      data.innerHTML = lines;
    };
    fr.readAsText(file);
  }

  //- if (item.isDirectory) {
  //-   let directoryReader = item.createReader();
  //-   directoryReader.readEntries((entries) => {
  //-     entries.forEach((entry) => {
  //-       scanFiles(entry, directoryContainer);
  //-     });
  //-   });
  if (item.kind === 'directory') {
    let directoryContainer = document.createElement("ul");
    container.appendChild(directoryContainer);
    for await (const [key, value] of item.entries())
    {
      scanFiles(value, directoryContainer);
    }
  }
}

dropzone.addEventListener(
  "drop",
  async (event) => {                                     //+ async
    let items = event.dataTransfer.items;

    event.preventDefault();
    listing.textContent = "";

    for (let i = 0; i < items.length; i++) {
      let item = await items[i].getAsFileSystemHandle(); //- .webkitGetAsEntry(); + await

      if (item) {
        scanFiles(item, listing);
      }
    }
  },
  false,
);
© www.soinside.com 2019 - 2024. All rights reserved.