在读取相同文件的Chrome和FireFox中,FileReader对象返回不同的值

时间:2018-07-13 08:33:18

标签: javascript google-chrome firefox

修改所选文件的内容后,以下代码(角度2)在Chrome和Firefox中返回不同的结果:

    isExistedFiles(funcCallBack: any) {
    try {
      const r = new FileReader();
      r.onerror = function (e: any) {
        funcCallBack(0);
      };
      r.onload = function (e: any) {
        funcCallBack(1);
      };
      r.readAsText(this.files);
    } catch (e) {
      funcCallBack(0);
    }
  }

结果:

-Firefox:FileReader { readyState: 2, result: null, error: DOMException,...

-Chrome:FileReader {readyState: 2, result: "PK ....", error: null,...

为什么会这样?以及如何解决?

1 个答案:

答案 0 :(得分:0)

对于在用户选择后在磁盘上修改的文件,它们确实具有不同的行为,并且IIRC甚至在不同的OS上也会更改此行为。
(此答案仅基于可能与您不匹配的macOS系统上的观察结果)

Chrome会在访问时更新文件的元数据。
Firefox不会在访问时更新这些元数据,因此,如果您尝试读取文件时的文件大小小于用户选择文件时的文件大小,则FileReader会引发错误。
这是因为,由于它使用了旧的元数据,因此要求它读取不存在的数据。

为了使其更加直观,让我们在用户选择时获取文件的内容:

abcdefghijklmnopqrstuvwxyz

当Firefox请求文件的元数据时,操作系统会告诉它size: 26

现在,让我们将该文件的内容更改为

abc

如果我们尝试通过FileReader读取此文件,则FF将使用操作系统赋予它的元数据(大小:26)。因此它将尝试读取直到该文件的第26个字节。
显然,这是行不通的...这就是您的为什么


那么,现在,“如何解决”?

好吧,这取决于您的意思...如果您希望Chrome在Firefox上具有行为,则可以使用blobURI和AJAX在磁盘上获取文件,然后将其实际上从磁盘加载到内存中,因此,带有新的元数据。

但是请注意,这在Safari中不起作用,它本身会从选定的文件中创建一个blobURI,但是如果更改了它,就不允许我们将其作为新文件从磁盘上获取...

另一种更丑陋的解决方法是,当用户选择文件时,只会“按原样”提供文件,而是在内存中创建文件的副本(我认为FileReader.readAsArrayBuffer是跨浏览器最有效的方法它)。但是,如果您的用户确实进行了修改,那么他们可能会很失望地看到他们的更改没有得到体现。

所以也许最好的解决方案是简单地处理错误,并向您的用户提供一条消息,向他们解释说修改已选择的文件并重新选择它是很不好的。

Ps:Highly related