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

Javascript FileReader对象在读取同一文件的Chrome和FireFox中返回不同的值,javascript,google-chrome,firefox,Javascript,Google Chrome,Firefox,在所选文件内容被修改后,下面的代码(angular 2)在Chrome和Firefox中返回不同的结果: isExistedFiles(funcCallBack: any) { try { const r = new FileReader(); r.onerror = function (e: any) { funcCallBack(0); }; r.onload = function (e: any) {

在所选文件内容被修改后,下面的代码(angular 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,结果:null,错误:DomeException,…

-Chrome:
FileReader{readyState:2,结果:“PK…”,错误:null,


为什么会发生这种情况?以及如何修复它?

对于用户选择后在磁盘上修改的文件,它们确实有不同的行为,甚至在不同的操作系统上,这种行为也会发生变化。
(此答案仅基于对macOS系统的观察,可能与您的不匹配)

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

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

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

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

abc
如果我们尝试通过文件读取器读取此文件,FF将使用操作系统提供给它的元数据(大小:26)。因此,它将尝试读取此文件的第26个字节。
显然,这不起作用…这就是你的原因


那么现在,“如何修复它”

好吧,这取决于你的意思……如果你想在Firefox上使用Chrome的行为,你可以使用blobURI adn AJAX在磁盘上获取文件,实际将文件从磁盘加载到内存,并因此使用新的元数据

但请注意,这在Safari中不起作用,Safari本身会从选定的文件创建blobURI,但如果它已被更改,则不允许我们在磁盘上获取新的blobURI

另一个更难看的解决方法是在用户选择文件时只给您“原样”的文件,即在内存中创建一个副本(我认为FileReader.readAsArrayBuffer是最跨浏览器的方法)。但是如果您的用户修改了它,他们可能会失望地看到他们的更改没有反映出来

因此,最好的解决方案可能是简单地处理错误,并向用户提供一条消息,向他们解释修改已选择的文件是不好的,然后让他们再次选择它


Ps:

chrome错误说明了什么?Firefox中的DomeException抱怨了什么?它报告了一条消息:“文件无法读取”。