78

我正在开发一个用作内部工具的 Chrome 扩展程序。其要求的行为是:

  1. 作为页面操作,在查看某些 Intranet 页面时启用地址栏图标。
  2. 当用户单击该图标时,识别页面上某种媒体类型(例如 .jpg)的所有文件,以及
  3. 静默地将它们全部保存到用户本地驱动器上的目录中。

以前有人问过这个问题,但当时的答案是“使用 NPAPI ”,而NPAPI 现在已被废弃

那么,目前实现这一目标的可用方法是什么?我看过的有:

  • chrome.FileSystem API ---但这不会将文件保存在任何用户可访问的位置。相反,存储的文件隐藏在未记录目录中的混淆名称后面。用户要求将文件以其原始名称存储在可访问的目录中。
  • HTML5 下载属性,通过创建一个 data: URL 并以编程方式单击它。这会为每个文件弹出一个“另存为...”对话框,当单个页面上有一百个资产时,这是不可接受的。用户要求下载文件而无需单击单个图标之外的进一步交互。
  • Chrome 下载 API,但仅在 beta 和 dev 通道中可用。用户需要此扩展程序与主流 Chrome 一起使用。
  • 通过创建一个简单地将文件保存到磁盘的小型 .exe,然后将 .jpg 作为 blob 传递给它,使用Native Messaging API 。这看起来很麻烦,我什至不确定如何可靠地将大 blob 传递给这样的 EXE。

我可以尝试另一种方法吗?

4

4 回答 4

54

你已经做了很多研究。事实上,没有任何插件或扩展,常规网页无法写入用户的文件系统。此外,如您所见, HTML5 文件系统 API仅提供对虚拟文件系统的访问。

但是,您将chrome.fileSystemAPI 与 HTML5 FileSystem API 混淆了。与 HTML FileSystem API 不同,Chrome 的fileSystem(app)API 可以直接写入用户指定的文件系统(例如~/Documents%USERPROFILE%\Documents)。

此 API 仅适用于 Chrome应用程序,不适用于扩展程序。这不是问题,特别是因为您正在开发内部工具,因为您可以安装应用程序和扩展程序,并使用消息传递在扩展程序(页面操作)和应用程序(文件系统访问)之间进行通信(示例)。


About chrome.downloads:由于您的扩展是内部的,您可能可以强制用户进入 beta/dev 频道以使用此 API。此 API 的唯一限制是文件将保存在用户定义的下载文件夹(的子目录)中。

编辑:chrome.downloadsAPI 现在可用于所有渠道,包括稳定分支(自 Chrome 31 起)。

于 2013-11-06T13:49:24.467 回答
6

恐怕您已经完成了作业,这意味着您查看了所有可能的替代方案。

准确实现您想要的最佳方式是(如您所述)使用支持的本机应用程序并通过本机消息传递进行通信。顺便说一句,由于带宽在 Intranet 上很少成为问题,您可能会发现传递资源(例如图像)URL 并让应用程序下载并保存它们更简单。
(是的,这将比简单地开发一个扩展更麻烦,但一个人必须做他们必须做的,对吧?)

另一方面,如果您愿意牺牲一点用户体验而不是开发简单性,我建议将 HTML5 好东西(允许您在本地创建和下载文件)与 JS 压缩库(例如JSZip)结合起来,所以用户只需要下载一个 zip 文件(并且只提示一次)。顺便说一句,如果用户愿意,他/她可以选择在不提示的情况下始终下载文件(但您已经知道了)。

于 2013-11-06T06:23:34.300 回答
3

使用 Native Messaging App 的想法。

本机应用程序很麻烦而且编写起来很痛苦,因为文档很差,除非您在两端获得完全正确的 JSON 格式,否则您将不会在控制台中看到任何内容,因为 stdin 和 stdout 被接管了。

但是,完成后您会更开心,因为您可以使用标准工具(例如,Windows 资源管理器、十六进制编辑器、TeamViewer...)来查看、移动和删除文件,或者查看正在发生的事情。Chrome 的沙盒文件系统可以工作,但现在似乎是一个死胡同(没有其他浏览器采用它)。没有人可能为它开发第三方工具。当然,一旦一切正常,您可能不需要工具,但在那之前,调试是一场噩梦,因为您需要编写代码(以及相当多的代码)来跟踪哪些文件在哪些目录、文件版本、剩余磁盘空间...

于 2014-11-20T21:33:26.200 回答
0

内部(或可能是非内部)使用的另一种解决方案是连接到本地或远程的 websocket 服务器。

你可以把它放在 background.js 或 content.js 中(使用wss://for https://

var ws = new WebSocket('ws://echo.websocket.org');
// var ws = new WebSocket('ws://127.0.0.1:9000');
ws.onmessage = function(res) {
    console.log('received data:', res.data);
};
ws.onopen = function() {
    ws.send('hello');
};
于 2020-05-06T01:43:46.567 回答