修改所选文件的内容后,以下代码(角度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,...
为什么会这样?以及如何解决?
答案 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是跨浏览器最有效的方法它)。但是,如果您的用户确实进行了修改,那么他们可能会很失望地看到他们的更改没有得到体现。
所以也许最好的解决方案是简单地处理错误,并向您的用户提供一条消息,向他们解释说修改已选择的文件并重新选择它是很不好的。