Firefox 网络扩展 - 读取本地文件(最后下载的文件)

Posted

技术标签:

【中文标题】Firefox 网络扩展 - 读取本地文件(最后下载的文件)【英文标题】:Firefox web extension - read local file (last downloaded file) 【发布时间】:2018-02-05 17:36:25 【问题描述】:

我正在创建一个 Web 扩展并从 XUL 移植。我以前可以很容易地用

读取文件
  var dJsm = Components.utils.import("resource://gre/modules/Downloads.jsm").Downloads;
  var tJsm = Components.utils.import("resource://gre/modules/Task.jsm").Task;
  var fuJsm = Components.utils.import("resource://gre/modules/FileUtils.jsm").FileUtils;
  var nsiPromptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);

  ....

  NetUtil.asyncFetch(file, function(inputStream, status) 
           if (!Components.isSuccessCode(status)) 
            return;
           
            var data =  NetUtil.readInputStreamToString(inputStream, inputStream.available());
            var data = window.btoa(data);
            var encoded_data_to_send_via_xmlhttp = encodeURIComponent(data);
            ...
  );

以上内容将被弃用。

我可以使用 downloads.download() 了解上次下载的内容,但我无法读取该文件,然后获取对应的 encoded_data_to_send_via_xmlhttp

同样在 Firefox 57 以后,这意味着我必须尝试通过单击按钮或其他方式来伪造用户操作,或者上传文件。

  Access to file:// URLs or reading files without any explicit user input 

有没有一种简单的方法可以读取上次下载的文件?

【问题讨论】:

从 url 读取文件,例如'/Downloads/random.txt' - 这是必须阅读然后发布的内容 查看this article 中的信息以及链接的代码示例。 没有帮助。我还是无法读取文件 可以通过 XMLHttp 读取下载的 url 设置为 blob,然后使用 FileReader.readAsDataURL() 读取 blob。但我不想这样做。有时 URL 会被阻止,以便下载存在于本地存储中。 为什么不将下载项目对象的 URL 发送到服务器,然后调用从 URL 到服务器的传输? 【参考方案1】:

WebExtension API 不再允许扩展读取本地文件。您可以让扩展程序获得 CORS 权限,并通过 fetch()XMLHttpRequest() 直接从 URL 读取内容作为 blob 并直接存储到 IndexedDB 或内存,然后编码并发送到服务器。这带有many restrictions and limitations,例如您可以从哪个来源读取等等。

此外,这可能会增加许多不需要的步骤。如果目前的问题似乎是为了与服务器共享下载的文件,我建议您获取最后一个 DownloadItem 对象,从中提取 URL (.url)对象并将 URL 发送回服务器。

这样,服务器可以直接从该 URL 加载(如果需要,可以在服务器上对其进行编码)。网络负载将大致相同(实际上会少一点,因为不涉及 Base64 编码,这会增加 33% 的大小),并且客户端上的负载要少得多。服务器会将数据读取为二进制/字节数据流;与直接从扩展程序发送数据差不多。

要获取最后下载的文件,您可以通过特权脚本执行以下操作:

browser.downloads.search(
  limit: 1,
  orderBy: ["-startTime"]
)
.then(getLastDownload);

function getLastDownload(downloads) 
  if (downloads.length) 
    var url = downloads[0].url;
    // ... send url to the server and let server fetch the data from it directly
  

【讨论】:

公平地说,我已经表明这在早期的 cmets 中是可能的,但似乎无法绕过解决方案。 我查看了本地消息传递并运行了一个小应用程序来为我完成繁重的工作,这并不理想,但鉴于 FF 中的 MDN 安全指南,我无法“读取”任何下载的文件.可以在 Web 扩展旁边安装一个应用程序以从下载 API 获取参数,然后在本地读取文件并将其发布到服务器 最后的 browser.downloads.search 实际上并没有 100% 地显示最后一次下载。如果下载正在进行中,我需要等待它完成然后将其发送到服务器,所以我选择使用 eventListener 来代替 我已经解决了这个问题,使用之前的方法通过 XMLHttp 读取下载的 url 将其设置为 blob,然后使用 FileReader.readAsDataURL() 读取 blob,然后将其发送到编码为 Base64 的服务器,只需我的下载可以被触发两次(一次来自用户点击,然后来自这个监听下载然后重新获取并发送它的过程......麻烦......【参考方案2】:

根据this support mozilla question.

(2) 本地文件安全

Firefox 限制从 Web 服务器上的页面访问本地磁盘或 UNC 路径上的页面。 [...])。

哪种解决方案?

使用local-filesystem-links firefox addon(未测试)

和/或

在客户端运行一个小型本地网络服务器,假设服务器以足够的权限运行,您最终可以通过 http:// 访问任何本地内容(但仍然不能使用 file:///)

【讨论】:

以上是关于Firefox 网络扩展 - 读取本地文件(最后下载的文件)的主要内容,如果未能解决你的问题,请参考以下文章

js如何读取本地txt文件中的内容

Unity 读取图片方法

PHP读取目录下所有文件

js读取xml文件-适用于firefox、chrome

CAD在网页中绘图,并为新绘的对象写扩展数据和读取扩展数据

软件测试 实验02 MAC环境下Firefox配置selenium java读取xlsx文件