前端文件操作

files属性的类型是FileList,从名字就可以看出它是一个类数组,类数组元素是File类型对象

那么如果input[type=file]标签选择多个文件(标签加一个multiple属性),它的files中应该会包含多个File对象元素

而从打印结果可以看出File类型对象就是我们选择的文件

File是啥

File - Web API 接口参考 | MDN (mozilla.org)")

MDN关于File的介绍:

作用:

文件(File)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。

如何产生File对象:

通常情况下, File 对象是来自用户在一个 元素上选择文件后返回的 FileList 对象,也可以是来自由拖放操作生成的 DataTransfer 对象,或者来自 HTMLCanvasElement 上的 mozGetAsFile() API。

File对象的属性

lastModified    只读。返回当前 File 对象所引用文件最后修改时间的毫秒数。

lastModifiedDate    只读。返回当前 File 对象所引用文件最后修改时间的 Date 对象。(废弃)

name    只读。返回当前 File 对象所引用文件的名字。

size    只读。返回当前 File 对象所引用文件的大小。

type    只读。返回当前 File 对象所引用文件的MIME类型

webkitRelativePath    只读。返回 File 相关的 path 或 URL。(不推荐)

其中lastModifiedDate,webkitRelativePath不推荐使用

剩下的属性也比较好理解,都是文件常见的信息,比如文件名,文件类型,文件大小,文件最后修改时间,需要注意这些File对象属性都是只读的。

File对象的方法

File对象没有定义任何方法,它的方法都继承自Blob。

原型链如下

可以发现File实例对象可以沿着原型链访问到Blob.prototype上的方法。

Blob是什么

Blob - Web API 接口参考 | MDN (mozilla.org)")

====================================================================================================================================================

MDN对于Blob介绍是:Blob 对象表示一个不可变、原始数据的类文件对象。

啥叫类文件对象?

Blob翻译过来是 Binary Larger Object,即二进制大对象。即Blob对象的组成是二进制数据。

而我们知道文件也是二进制编码的数据。

那么为什么Blob叫类文件呢,而不是文件呢?

其实Blob在这里代表的是比文件更加底层的概念。

我们知道文件是由二进制数据组成的,那么我们随意编写一些二进制数据,它能代表一个文件吗?答案是不能。文件的二进制数据具有各种特殊标识,来帮助外部理解一堆二进制数据是一个文件。

Blob代表的其实就是文件的切片。

我们知道文件的二进制数据组合在一起才能代表文件,而文件的二进制数据被分段后,比如分成十段,那么每一段都无法表示文件。但是每一段又都是文件的必不可少的组成部分。

此时就需要Blob来表示这些文件切片。所以说Blob是一个类文件对象。它不是文件,但是却和文件有千丝万缕的关系。

在浏览器API中,Blob是File的父类,这很好理解,父类是基类,子类是扩展类,我们可以说文件File是一堆二进制数据,是一个特殊的Blob,它可以当成Blob。但是它又比Blob多了一层含义。

Blob对象的属性:

size    只读。Blob 对象中所包含数据的大小(字节)。

type    只读。一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。

有人说Blob对象咋还有文件才有的MIME类型呢?它不就是一个二进制数据对象吗?

还是要再说明一下,Blob对象相当于File对象的切片,如何标识一个文件切片属于什么文件类型是有必要的,它涉及都二进制数据的解析。

Blob对象的方法:

Blob.slice([start[, end[, contentType]]])    返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。

Blob.stream()    返回一个能读取blob内容的 ReadableStream。

Blob.text()    返回一个promise且包含blob所有内容的UTF-8格式的 USVString。

Blob.arrayBuffer()    返回一个promise且包含blob所有内容的二进制格式的 ArrayBuffer

Blob构造函数

Blob(blobParts[, options])

返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成。

其中blobParts参数是一个数组,数组中的每一项元素连接起来构成Blob对象的数据,数组中的每项元素可以是ArrayBuffer, ArrayBufferView, Blob, DOMString 。

options:可选项,字典格式类型,可以指定如下两个属性:

type,默认值为 “”,它代表了将会被放入到blob中的数组内容的MIME类型。

endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: “native”,表示行结束符会被更改为适合宿主操作系统文件系统的换行符; “transparent”,表示会保持blob中保存的结束符不变。

File,Blob的slice方法

那么现在了解Blob,而File继承了Blob的所有方法,且进行了拓展,可以直接操作文件,比如文件分片slice

从打印结果可以看出,file经过slice得到文件切片file_cp,而file_cp就不再是File类型了,而是Blob类型。

File,Blob的text方法

file.text()返回一个promise,该promise对象的结果是 blob所有内容的UTF-8格式的 USVString。

即file.text()将二进制编码的数据 转成了 utf-8编码的文本字符串。

不知道意义何在…,就像你用Notepad++打开一张png格式的图片一样。

File,Blob的arrayBuffer方法

file.arrayBuffer()

file.arrayBuffer()返回一个promise对象,其结果是 blob所有内容的二进制格式的 ArrayBuffer

ArrayBuffer是啥


那么啥是ArrayBuffer呢?ArrayBuffer - JavaScript | MDN (mozilla.org)")

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。

它是一个字节数组,通常在其他语言中称为“byte array”。

你不能直接操作 ArrayBuffer 的内容,而是要通过 TypeArray 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

为什么ArrayBuffer中的数据无法直接操作呢?

因为ArrayBuffer数组的元素都是字节,即八位二进制数,且是二进制编码的,我们无法将ArrayBuffer字节数组的字节元素取出来,也无法覆盖字节元素。因为我们输入的都是字符,而不是字节。

而我们知道八位二进制数 可以转成 其他类型数据,最常见就是十进制数值,而我们是可以输入十进制数值的,所以可以将ArrayBuffer字节数组转为TypeArray类型数组,常见的TypeArray数组有:

由于ArrayBuffer都是字节元素,即每个元素都是无符号8位2进制,所以我们通常是将ArrayBuffer转为Unit8Array来进行处理

此时我们就可以对字节数组转成的Uint8Array数组进行元素操作了

对Uint8Array修改完后,再将其转为ArrayBuffer,则很简单,Uint8Array对象上就有一个buffer属性,可以获取到之前的ArrayBuffer实例

另外TypeArray没有新增,删除元素的操作,因为TypeArray的数组长度是固定的,无法改变的。

所以这么一看ArrayBuffer除了可以转为TypeArray修改字节元素外,也没啥,关键谁没事改字节数啊,文件的字节被改了,可能都无法解析了。

File,Blob的stream方法

file.stream()

返回一个能读取blob内容的 ReadableStream。

那么什么是ReadableStream呢?ReadableStream - Web API 接口参考 | MDN (mozilla.org)

流操作API 中的ReadableStream 接口呈现了一个可读取的二进制流操作。

啥叫二进制流?

我们知道程序上的各种数据在计算机底层上都是二进制形式的,而程序中可识别数据互相传递,就意味着二进制形式数据的传输,即一串010101在各个程序中传输,而这些传输都是有方向性,就像水流一样,总是朝着一个方向流动,不可能出现一股水流出现两个方向。所以二进制数据的传输也是如此,所以二进制数据传输,也叫做流。

那么流的方向有哪些呢?

一个程序需要外部传入数据,那就底层的二进制数据就是朝着该程序输入,也叫输入流。

一个程序向外部提供数据,那么底层二进制数据就是朝程序外输出,也叫输出流。

具体判断是输入流,还是输出流的要点是,数据源是谁,如果从数据源读取数据,那么相当于数据源对外输出,就是输出流,如果向数据源写入数据,那么相当于输入流。

所以一个文件的输出流一般和读操作相关,输入流和写操作相关。

另外有一个关于流的概念,那就是流的组成。

我们知道流是指二进制数据的流动,那么流的组成就是二进制数据。但是二进制数据有不同的形式:

比如 0000000000001111111111111100000000000000,和 00000000 00001111 11111111 11000000 00000000

二者二进制数都相同,都表示40位的二进制数,但是第二个按照8位一组,进行了分组。

我们知道 8 bit = 1 Byte,即8位二进制数 相当于一个字节。

所以在传输中的流有了两个概念,比特(bit)流,和字节(Byte)流,字节流就是将比特流按照8位一组进行分组后的二进制数据。

而在字节之上就是字符了,字符指的就是人类可以识别的文字,而字节是计算机可以识别的文字。

人们制定了各种编码方式,将字节组合起来代表一个人类世界的字符。

比较有名的编码有:ASCII码(英语系编码),GBK码(汉语系编码),UTF-8码(世界所有语言编码)

由于英语只有26字母以及一些常用的英语符号,所以ASCII码只需要一个字节(相当于8位二进制数,可以有255种对应关系)就可以代表所有英语系常用字符。

而汉语有成千上万的文字,即使按照偏旁部首进行分类,也有很多,所以GBK字符需要两个字节(相当于16位二进制数,可以有 2^16 - 1 = 65535种对应关系)

而想要表示世界上所有语言,UTF-8的字符需要三个字节(相当于24位二进制数,即2^24-1种对应关系。)

而无论操作系统,还是浏览器,还是程序编写工具,还是记事本,它们都是直接面向人类的,所以他们需要将字节 按照对应编码规则 转化为 字符。

所以字节流  在进行分组,即按照编码规则分组,比如UTF-8编码,将三个字节分为一组,形成字符流。

而无论是比特流,还是字节流,还是字符流,它们都有流向,即可以分为输入流和输出流。

如果是基于文件的读取和写入的话,那么也可以叫做 读取流(输出流) 和 写入流(输入流)。

ReadableStream 是啥

那么ReadableStream 接口呈现了一个可读取的二进制流操作。

其实就是说 以字节流的方式读取文件中二进制数据 的 操作

ReadableStream的属性

locked    只读。locked 返回这个可读流是否被一个读取器锁定

ReadableStream对象的方法

cancel    取消读取流,读取方发出一个信号,表示对这束流失去兴趣。可以传入 reason 参数表示取消原因,这个原因将传回给调用方。

getIterator    创建一个异步的 ReadableStream 迭代器并将流锁定于其上。一旦流被锁定,其他读取器将不能读取它,直到它被释放。

getReader    创建一个读取器并将流锁定于其上。一旦流被锁定,其他读取器将不能读取它,直到它被释放。

pipeThrough    提供将当前流管道输出到一个 transform 流或 writable/readable 流对的链式方法。

pipeTo    将当前 ReadableStream 管道输出到给定的 WritableStream (en-US),并返回一个 promise,输出过程成功时返回 fulfilled,在发生错误时返回 rejected。

tee    tee 方法(tee本意是将高尔夫球放置在球座上)tees 了可读流,返回包含两个ReadableStream 实例分支的数组,每个元素接收了相同的传输数据。

看了一下ReadableStream的各种方法,水很深,暂时搁置一下,后面有时间再分析把。

File,Blob,ArrayBuffer小结

以上,我们了解了File,Blob,ArrayBuffer的一些基本概念和功能。

我们知道了File,Blob,ArrayBuffer都是二进制数据对象,

其中File是文件级别二进制对象,Blob和ArrayBuffer都是普通二进制对象

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后

文章到这里就结束了,如果觉得对你有帮助可以点个赞哦,如果有需要前端校招面试题PDF完整版的朋友可以点击这里即可获取,包括答案解析。

5650)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-JOUB2mz8-1711684255651)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(资料价值较高,非无偿)

最后

文章到这里就结束了,如果觉得对你有帮助可以点个赞哦,如果有需要前端校招面试题PDF完整版的朋友可以点击这里即可获取,包括答案解析。

[外链图片转存中…(img-jkgCNaIw-1711684255651)]

  • 11
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值