Firefox 网络扩展 - 读取本地文件(最后下载的文件)
Firefox web extension - read local file (last downloaded file)
我正在创建一个 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
没有一种简单的方法可以读取上次下载的文件吗?
WebExtension API 将不再允许扩展程序读取本地文件。您可以让扩展程序获得 CORS 权限,并通过 fetch()
或 XMLHttpRequest()
直接从 URL 读取内容作为 blob 并直接存储到 IndexedDB 或内存,然后编码并发送到服务器。这带有 many restrictions and limitations,例如您可以从哪个来源读取等等。
此外,这可能会增加许多不需要的步骤。如果目前的问题似乎是为了与服务器共享下载的文件,我建议您获取最后一个 DownloadItem
对象,提取 URL ( .url
) 从该对象并将 URL 发送回服务器。
这样服务器可以直接从 URL 加载(并在需要时在服务器上对其进行编码)。网络负载将大致相同(实际上要少一些,因为不涉及 Base64 编码,这会增加 33% 的大小),并且客户端的负载要少得多。服务器会将数据读取为 binary/byte 数据流;与直接从扩展程序发送数据一样。
要获取最后下载的文件,您可以从特权脚本中执行以下操作:
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
}
}
根据this support mozilla question。
(2) Local file security
Firefox limits access from pages on web servers to pages on local disk or UNC paths. [...]).
哪个解决方案?
and/or
- 运行 客户端的小型本地网络服务器,假设服务器 运行 具有足够的权限,您最终可以通过 http:// 访问任何本地内容(但仍然不能使用 file:/ //)
我正在创建一个 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
没有一种简单的方法可以读取上次下载的文件吗?
WebExtension API 将不再允许扩展程序读取本地文件。您可以让扩展程序获得 CORS 权限,并通过 fetch()
或 XMLHttpRequest()
直接从 URL 读取内容作为 blob 并直接存储到 IndexedDB 或内存,然后编码并发送到服务器。这带有 many restrictions and limitations,例如您可以从哪个来源读取等等。
此外,这可能会增加许多不需要的步骤。如果目前的问题似乎是为了与服务器共享下载的文件,我建议您获取最后一个 DownloadItem
对象,提取 URL ( .url
) 从该对象并将 URL 发送回服务器。
这样服务器可以直接从 URL 加载(并在需要时在服务器上对其进行编码)。网络负载将大致相同(实际上要少一些,因为不涉及 Base64 编码,这会增加 33% 的大小),并且客户端的负载要少得多。服务器会将数据读取为 binary/byte 数据流;与直接从扩展程序发送数据一样。
要获取最后下载的文件,您可以从特权脚本中执行以下操作:
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
}
}
根据this support mozilla question。
(2) Local file security
Firefox limits access from pages on web servers to pages on local disk or UNC paths. [...]).
哪个解决方案?
and/or
- 运行 客户端的小型本地网络服务器,假设服务器 运行 具有足够的权限,您最终可以通过 http:// 访问任何本地内容(但仍然不能使用 file:/ //)