【问题标题】:Reading a collection of external files locally in JavaScript在 JavaScript 中本地读取外部文件的集合
【发布时间】:2017-03-02 02:38:47
【问题描述】:

我正在开发一个需要访问外部文件集合的应用。它基本上是一个音乐播放器。它在 Web 服务器下按预期工作,但我也希望它在浏览器中本地工作。

一般概述:

  • index.htm(带标记的小索引文件,收集外部js、css)
  • index.js(所有应用代码都在这里)
  • dir.js(所有音乐文件的文件路径数组)
  • /AHX/(音乐文件的位置)
  • ahx.js(音乐播放器代码)

这方面的两个主要困难是:

  1. JavaScript 无法列出目录内容,即使它是子目录。相反,我将文件路径表示为字符串数组。
  2. 只能使用 XMLHttpRequest 加载外部文件,它在本地/离线运行时有安全限制,但在其他环境下也有效(在 HTTP 或 Chrome App 下,可能是其他平台,不确定)。

奇怪的是,在最新的 Firefox 中,2) 不再是问题。 XMLHttpRequest 在本地工作而不禁用 security.fileuri.strict_origin_policy。我不确定这是否是标准行为,但 Chrome 似乎不允许这样做。

无论如何,我当前的解决方案是在 .js 文件中生成文件路径列表(以前我使用需要 XHR 的 txt 文件),并使用 XMLHttpRequest 加载音乐文件。这当然意味着我需要保持文件夹结构和文件路径数据库同步,使用 shell 脚本重建 dir.js 文件。

XHR 只能通过 HTTP 运行,因此该应用程序需要一个 Web 服务器。我希望该应用程序在本地运行(而不仅仅是强制用户安装为 Chrome 应用程序)。所以我问这个问题是为了找到读取数据的替代方法。

我尝试的另一种方法是将所有 1000 个文件编码为 base64 字符串并将其存储在 JS 对象中。这会生成一个相当大的 8MB .js 文件。加载速度似乎并不慢,但我认为它的效率并不高……而且更新/维护也很痛苦。

localStorage、IndexedDB 和 Web SQL 都是选项,但无法在应用程序运行之前预先填充存储。或许利用 File API 一次性设置存储数据库。

回到我的问题:访问大量二进制文件(200 多个文件,超过 6MB 等)本地(即直接打开 .html 文件)有哪些解决方案?

编辑:The app in question on GitHub,以消除对我的用例的任何困惑。但总的来说,我正在寻找在本地自动从应用程序读取这些音乐文件的方法,而不会出现跨域错误。此外,here 是 'js-database' 版本。它将所有 1000 个文件存储在一个 8MB 的 js 文件中,如下所示:

[{data:"base64-string-of-data-here",path:"original-path-here"}, ...]

通过这种方式,它绕过了对 XHR 的需求。

Edit2:使用jszip 和IndexedDB 的解决方案看起来很有希望。无法从多个选定文件夹加载多个文件,但如果目录树被压缩,jszip 可以访问格式为/FOLDER_HERE/FILE_HERE 的所有文件的数组。然后可以一次性设置将路径和二进制数据导入 IndexedDB。它也适用于file:// URL,这很重要。

jszip 也有可能用于有效地构建/更新内容的 BASE64 字符串的大型 JSON 结构,这不需要用户进行任何设置。不过还需要测试。

【问题讨论】:

  • 如果要在本地使用,为什么不使用 localStorage 而不是文件?
  • 在本地执行时,您的应用程序会被包装在可执行文件中(其中包含本地服务器),还是直接在浏览器中作为 html/js 文件运行?如果是第二种情况,您可能需要在代码中实现额外的安全性,以防止用户修改您的源文件。
  • @Kaddath 直接是html/js。该应用程序本身既可以作为 Chrome 应用程序运行,也可以作为普通网页应用程序运行。我为什么要关心用户是否修改了源?它基本上是开源的,完全离线运行。我不确定可执行的 JS 应用程序是如何运行的(电子/节点?),但如果有意义的话,我希望代码尽可能跨目标。基本上,如果我的应用在 Firefox 中打开 HTML 时可以正常工作,我想保留基本的浏览器功能,并检测仅在其他目标下工作的功能。
  • @juvian 需要从某处读取数据。如果有人第一次运行 .html,则 localStorage 数据必须在应用程序启动之前已经存在。如果应用可以加载数据,为什么还要额外插入到 localStorage 中?
  • @bryc 我不完全了解您的用例。您说您希望应用程序已经拥有数据并完全离线运行。那么数据存储在哪里呢?至于编码音乐文件,这里有一个类似的解决方案:stackoverflow.com/questions/14074833/…

标签: javascript browser xmlhttprequest filesystems local


【解决方案1】:

不要把这个当成确定的答案,这个话题我也很感兴趣,如果周围的人不想花时间详细说明答案,请发表评论,它比投票更有用..

从我在 javascript 资源中学到的知识,考虑到您不能真正绕过问题的安全方面。即使是开源的,如果你没有考虑到安全性,你也应该明确警告。例如,人们可以分发资源的修改版本。这取决于资源的用途。

如果这是针对玩家的,我建议将其视为数据资源,而不是脚本资源,因为安全性(只要您不评估字符串等)。 JSON 数据可以在这里完成这项工作,但这需要处理 1000 个文件。不过,编写一个处理文件的脚本并不难。

HTML5 文件 API

我还没有使用它,所以我可以给你一两个链接。缺点是它会将您的播放器限制在最近的浏览器中。

https://www.html5rocks.com/en/tutorials/file/dndfiles/

HTML5 File API read as text and binary

(我知道,不是答案)使用库:

除了在这种情况下,这可能是一个答案,只是因为 javascript 中没有真正的通用数据检索。一个好的库会添加它并支持旧浏览器。

在这些解决方案中,例如 jQuery JSONP 允许执行动态跨域 GET 请求。使用数据格式化(而不是脚本),注入更安全。但请记住,您应该详细了解您的播放器如何处理二进制文件,以及在何种情况下可能存在风险。

http://api.jquery.com/jQuery.getJSON/

直接包含脚本:不推荐

<script src="./sameFolderFile.js"></script>

至于在本地文件夹结构中直接包含脚本,它实际上在本地工作。 IE 说有 ActiveX 内容并要求使用权限,但它在 firefox 和 chrome 中有效。标签可以动态添加,但是这里存在很大的安全隐患:资源中添加的恶意javascript代码会被执行。这可能会给用户带来风险

【讨论】:

  • 我大量使用了File API,它非常好,但需要用户手动加载文件。但是,如果与 localStorage 或 IndexedDB 结合使用,它可以在之后从 IndexedDB 加载。使用 XHR 或 Fetch 是即时的,是的,安全受限于 file:// 协议。也就是说,该应用程序不是跨域的,如果可以将恶意代码添加到 sameFolderFile.js 中,则每个文件资产应用程序都可能受到损害。没有依赖关系,它只需要 XHR 的网络服务器或 chromeApp 实例。我想消除对网络服务器的需求。
猜你喜欢
  • 2021-09-19
  • 1970-01-01
  • 2022-08-13
  • 1970-01-01
  • 2012-02-17
  • 1970-01-01
  • 2014-02-26
相关资源
最近更新 更多