用户进行文件更改时,FileAPI不会更新文件大小(非webkit浏览器)

时间:2012-05-18 04:11:18

标签: javascript html5 firefox webkit fileapi

我想我先用一个例子说明问题,

jsfiddle:http://jsfiddle.net/e2UfM/15/ (经过FF 12和Chrome 18.0.1025.168测试)

用法:

  • 从本地计算机加载文本文件。
  • 点击“加载文件”。
  • 点击“显示文件大小” - 记下大小。
  • 修改&将文本文件保存在本地计算机上。
  • 再次点击“显示文件大小”。请注意,在webkit浏览器(Chrome)中文件大小如何变化,但在Firefox中它没有更新文件大小

当用户对他们选择的本地文件进行更改时,非webkit浏览器不会更新其大小属性,而Chrome则会更新。两个浏览器都会更新文件的内容。

有没有办法让Firefox更新文件大小,类似于Chrome在这种情况下的工作方式?


简单的真实世界示例:

用户选择一个对于表单来说太大的文件,他们点击提交按钮并收到通知他们的文件太大(通过警报,“大小”栏(见下文)等)

他们在本地修改文件,然后再次点击提交。

在Chrome中,文件大小会更新。当用户再次点击提交按钮时,它将再次验证其更新大小并允许上传。在Firefox中,用户必须先重新选择表单上的文件,然后才能看到文件大小的变化。

Firefox的部分解决方法 - @ ZER0的answer


真实世界的例子(深入):

如果我没有弄错的话,File API的一个目的是在上传到服务器之前验证客户端的文件大小。

考虑表单中有2MB上传限制并且用户选择1MB文件的情况。 Firefox和Chrome都会看到文件大小小于2MB并将其添加到表单中。我们还要说有一个简洁的条形图显示它们选择了多大的文件,以及它是否符合文件大小限制:

The 1MB file that the user has chosen!

但是,然后用户决定对本地文件的内容进行微小更改之前他们提交表单并将大小超过2MB。

在Google Chrome中,我可以在客户端优雅地处理此问题。我可以在用户提交表单时再次检查文件大小,并在将其发送到服务器之前验证它实际上仍然低于1MB。但即使在用户提交表单之前,在Chrome中,我可以动态更新小条形图,因为它们会在本地进行更改:

Now the file is over 2MB, bad!

如果用户填写的是大型表格,则此“栏”(或即时通知中的任何其他表格,例如提醒)非常有用。我希望用户立即知道他们的文件太大,以便他们可以更正它,而不仅仅是当他们提交表单时。

在Firefox中,因为文件大小永远不会更新,所以很乐意上传2MB文件,认为它仍然是1MB!我使用服务器端逻辑来仔细检查文件大小,但我宁愿保存服务器之旅。


我是如何遇到这个错误的:

以上示例与更多人有关,因为更多人可能处理表单中的文件上传与使用slice function in the File API。这是我遇到问题的具体方式。

在我的表单中,用户选择一个文件,当他们点击提交时,只有最后10,000个字节显示在textarea的屏幕上,以确认它确实是他们想要的文件。

考虑一个大小为50,000字节的文件。用户在表单中选择它,Chrome和Firefox在40,000 - 50,000中显示字节textarea

现在用户将一些内容添加到文件中,并将同一文件压缩到70,000个字节!

Google Chrome会正确更新textarea以包含字节60,000-70,000。在Firefox中,由于大小将保持不变,因此它仍然只显示40,000-50,000范围内的字节。


编辑:更新了jsfiddle,以证明FF仍然可以读取更新的文件内容。只是文件大小不会随着这些新内容而改变。

修改: https://bugzilla.mozilla.org/show_bug.cgi?id=756503(错误报告)

编辑:已添加示例&更新以回应@EduárdMoldován的comment& @ ZER0的answer。谢谢!

1 个答案:

答案 0 :(得分:1)

您似乎直接从size属性获取,并且由于此表单元素中的值未更改,因此Firefox可能也不会更新size属性。

作为解决方法,您可以查看已阅读内容的length。因此,而不是file.size evt.target.result.length

然而,这对我来说绝对是一个错误,所以你已经把它添加到Bugzilla上了!

<强>更新: 您仍然可以使用slice的字符串版本。否则,如果您愿意(或result是特定类型的数据),您可以从evt.target.result创建一个新的Blob对象(文件对象使用此界面),您可以在其中使用size属性和slice方法。