HTML5的File.slice方法实际上是在做什么?

39

我正在使用自定义 API 与用户一起上传文件(希望大小不受限制)。如果文件太大,它将被分成块,并在多个请求中处理到服务器。

我正在编写代码,根据网上的很多示例使用 FileFileReader(HTML5)。通常情况下(从网上读取的信息来看),对于分块文件传输,人们会先从文件对象中获取数据块。

var file = $('input[type=file]')[0].files[0];
var blob = file.slice(start,end)

接下来使用 FileReader 读取 blob 数据,可以使用 readAsArrayBuffer(blob)readAsBinaryString(blob)

最后在 FileReader.onload(e) 方法中将数据发送到服务器。对文件中的所有块重复此过程。

我的问题是

为什么我需要使用 FileReader?如果我不使用它,只是使用 File.slice 发送 blobs ,是否有保证切片操作会在每个请求中尝试发送数据之前完成。创建 File 对象时,是否会加载整个文件(肯定不会吧?)。File.slice 是否会寻找参数指定的位置,然后读取信息?文档没有给出如何实现的线索。

1个回答

51
需要翻译的内容如下:

需要记住的重要事情是,File 继承自 Blob,实际上 File 并没有 slice 方法,它从 Blob 中获取了这个方法。File 只增加了一些元数据属性。

最好的方式是将 Blob(或 File)视为指向数据的指针,而不是数据本身。有点像其他语言中的文件句柄。

如果没有使用读取器,则无法实际访问 Blob 中的数据,因为读取器会异步读取以避免阻塞 UI 线程。

Blob 的 slice() 方法只返回另一个 Blob,但这不是数据,而是原始 Blob 中一定范围内数据的指针,有点像带界限的指针视图。要从切片的 Blob 中获取字节,您仍然需要使用读取器。在切片 Blob 的情况下,读取器是带有范围的。

这实际上只是为了方便起见,以便您不必在代码中携带大量相对和绝对偏移量,您可以只获取数据的带界限视图,并像从第 0 字节处读取一样使用读取器。

在 XMLHttpRequest 的情况下(假设浏览器支持较新的接口),数据将在发送时进行流式传输,并受到 blob 范围的限制。基本上,它将按照您想象的方式工作,如果您将文件指针发送到流方法中(这基本上是在内部发生的)。https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data#Sending_binary_data

本质上,它是一种懒惰的读取器。如果该 Blob 已经从文件系统中加载/读取或者是在内存中创建的,则它将直接使用该数据。但是如果使用 File,它将被懒惰地加载并异步流式传输出主线程。

基本逻辑是,浏览器开发人员从不希望同步读取发生,因为它可能会阻塞主线程,因此所有API都围绕这个核心理念设计。注意Blob.slice()是同步的 - 这就是你知道它实际上没有进行任何IO操作,它只是设置边界和(可能)文件指针。

3
谢谢您为我解释“文件”的概念,现在更容易理解了。但是,如果我仍然使用返回一个 blob 的 File.Slice 方法,并尝试使用 XMLHttpRequest.send(myBlob) 将该 blob 发送到服务器,那么数据何时从文件中检索并传递给服务器?或者这样做会失败/不发送任何数据吗? - Ponml
1
我更新了我的答案,以便提供更多细节。当我编写我的JavaScript rsync实用程序时,我深入研究了这些东西:https://github.com/claytongulick/bit-sync - Clayton Gulick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接