在Blob对象中提到读取Blob对象时,可以使用FileReader对象。本篇文件详细介绍关于File的使用

HTML5中的Blob对象只是二进制数据的容器,本身并不能操作二进制。

File 对象代表一个文件,用来读写文件信息。它继承了 Blob 对象,或者说是一种特殊的 Blob 对象,所有可以使用 Blob 对象的场合都可以使用它。

File对象

File()构造函数接受三个参数。

  • array:一个数组,成员可以是二进制对象或字符串,表示文件的内容。
  • name:字符串,表示文件名或文件路径。
  • options:配置对象,设置实例的属性。该参数可选。

第三个参数配置对象,可以设置两个属性。

  • type:字符串,表示实例对象的 MIME 类型,默认值为空字符串。
  • lastModified:时间戳,表示上次修改的时间,默认为Date.now()。

    1. let file = new File(
    2. ['foo'],
    3. 'foo.txt',
    4. {
    5. type: 'text/plain',
    6. }
    7. );

    File 对象有以下实例属性。

  • File.lastModified:最后修改时间

  • File.name:文件名或文件路径
  • File.size:文件大小(单位字节)
  • File.type:文件的 MIME 类型
    1. var myFile = new File([], 'file.bin', {
    2. lastModified: new Date(2018, 1, 1),
    3. });
    4. myFile.lastModified // 1517414400000
    5. myFile.name // "file.bin"
    6. myFile.size // 0
    7. myFile.type // ""
    由于myFile的内容为空,也没有设置 MIME 类型,所以size属性等于0,type属性等于空字符串。
    File 对象没有自己的实例方法,由于继承了 Blob 对象,因此可以使用 Blob 的实例方法slice()。

    FileReader对象

    FileReader主要用于将文件内容读入内存,通过一系列异步接口,可以在主线程中访问本地文件。

FileReader 对象用于读取 File 对象或 Blob 对象所包含的文件内容。
浏览器原生提供FileReader构造函数,用来生成 FileReader 实例。

  1. let reader = new FileReader();

FileReader对象的方法

方法定义 描述
abort():void 终止文件读取操作
readAsArrayBuffer(file):void 异步按字节读取文件内容,结果用ArrayBuffer对象表示
readAsBinaryString(file):void 异步按字节读取文件内容,结果为文件的二进制串
readAsDataURL(file):void 异步读取文件内容,结果用data:url的字符串形式表示
readAsText(file,encoding):void 异步按字符读取文件内容,结果用字符串形式表示

FileReader对象实例的属性

事件名称 描述
error 读取文件时产生的错误对象
readyState 表示读取文件时的当前状态,一共有三种可能的状态,0表示尚未加载任何数据,1表示数据正在加载,2表示加载完成。
result 读取完成后的文件内容,有可能是字符串,也可能是一个 ArrayBuffer 实例。
onabort 当读取操作被中止时调用
onerror 当读取操作发生错误时调用
onload 当读取操作成功完成时调用
onloadend 当读取操作完成时调用,不管是成功还是失败
onloadstart 当读取操作将要开始之前调用
onprogress 在读取数据过程中周期性调用

FileReader 使用

FileReader提供了四种不同的读取文件的方式:

  • FileReader.readAsText():返回文本,需要指定文本编码,默认为 UTF-8。
  • FileReader.readAsArrayBuffer():返回 ArrayBuffer 对象。
  • FileReader.readAsDataURL():返回 Data URL。
  • FileReader.readAsBinaryString():返回原始的二进制字符串。

    text类型内容

    ```javascript // HTML 代码如下

// javascript var input = document.getElementById(“file”); //input file input.onchange = function(){ var file = this.files[0]; if(!!file){ //读取本地文件,以utf-8编码方式输出 var reader = new FileReader(); reader.readAsText(file,”utf-8”); reader.onload = function(){ //查看文件输出内容 console.log(this.result); //查看文件内容字节大小 console.log(new Blob([this.result])) } } }

  1. 读取到text类型文件,并显示到页面。通过注册onprogressonerror等事件,记录文件读取进度或异常行为等等。<br />**读取的txt文件**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/737887/1647096568708-f68c7b87-4d68-4b92-bc68-fdf469a02827.png#clientId=u2bf720c1-110f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=86&id=uea44b73f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=132&originWidth=412&originalType=binary&ratio=1&rotation=0&showTitle=false&size=11512&status=done&style=none&taskId=udfc23c86-61bc-45bc-893e-869640cb24e&title=&width=269)<br />**读取到png图片**<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/737887/1647096595833-deb9a878-d981-45d8-befd-f0731caa4f66.png#clientId=u2bf720c1-110f-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=266&id=ubf9d0a96&margin=%5Bobject%20Object%5D&name=image.png&originHeight=532&originWidth=1218&originalType=binary&ratio=1&rotation=0&showTitle=false&size=193906&status=done&style=none&taskId=u036fccf5-48e4-4c56-aad6-8f2c564f99c&title=&width=609)<br />readAsText读取文件的单位是字符,故对于文本文件,只要按规定的编码方式读取即可;<br />而对于媒体文件(图片、音频、视频),其内部组成并不是按字符排列,故采用readAsText读取,会产生乱码。
  2. <a name="kNBZn"></a>
  3. #### BinaryString类型
  4. ```javascript
  5. // HTML 代码如下
  6. <input type="file" id="file"></input>
  7. // javascript
  8. var input = document.getElementById("file"); //input file
  9. input.onchange = function(){
  10. var file = this.files[0];
  11. if(!!file){
  12. //读取本地文件,以gbk编码方式输出
  13. var reader = new FileReader();
  14. reader.readAsBinaryString(file);
  15. reader.onload = function(){
  16. //查看文件输出内容
  17. console.log(this.result);
  18. //查看文件内容字节大小
  19. console.log(new Blob([this.result]))
  20. }
  21. }
  22. }

读取文本
image.png
读取图片
image.png
readAsBinaryString,会让数据变大

ArrayBuffer类型

  1. // HTML 代码如下
  2. <input type="file" id="file"></input>
  3. // JavaScript
  4. var input = document.getElementById("file"); //input file
  5. input.onchange = function(){
  6. var file = this.files[0];
  7. if(!!file){
  8. //读取本地文件,以gbk编码方式输出
  9. var reader = new FileReader();
  10. reader.readAsArrayBuffer(file);
  11. reader.onload = function(){
  12. //查看文件输出内容
  13. console.log(this.result);
  14. //查看文件内容字节大小
  15. console.log(new Blob([this.result]))
  16. }
  17. }
  18. }

读取到文本
image.png
读取到图片打印的数据
image.png
与readAsBinaryString类似,readAsArrayBuffer方法会按字节读取文件内容,并转换为ArrayBuffer对象。

DataURL类型

  1. // HTML 代码如下
  2. <input type="file" id="file"></input>
  3. // JavaScript
  4. let input = document.getElementById("file"); //input file
  5. input.onchange = function(){
  6. var file = this.files[0];
  7. if(!!file){
  8. //读取本地文件,以gbk编码方式输出
  9. var reader = new FileReader();
  10. reader.readAsDataURL(file);
  11. reader.onload = function(){
  12. //查看文件输出内容
  13. console.log(this.result);
  14. //查看文件内容字节大小
  15. console.log(new Blob([this.result]))
  16. }
  17. }
  18. }

读取文本
image.png
读取图片
image.png

项目中实际应用

在线预览本地文件

img的src属性或background的url属性,可以通过被赋值为图片网络地址或base64的方式显示图片。
在文件上传中,我们一般会先将本地文件上传到服务器,上传成功后,由后台返回图片的网络地址再在前端显示。
通过FileReader的readAsDataURL方法,可以不经过后台,直接将本地图片显示在页面上。这样做可以减少前后端频繁的交互过程,减少服务器端无用的图片资源,

  1. // HTML 代码如下
  2. <input type="file" id="file"></input>
  3. <img id="file_img"></img>
  4. // JavaScript
  5. let input = document.getElementById("file"); //input file
  6. input.onchange = function(){
  7. var file = this.files[0];
  8. if(!!file){
  9. //读取本地文件,以gbk编码方式输出
  10. var reader = new FileReader();
  11. reader.readAsDataURL(file);
  12. reader.onload = function(){
  13. //查看文件输出内容
  14. console.log(this.result);
  15. //查看文件内容字节大小
  16. console.log(new Blob([this.result]))
  17. // 显示图片
  18. document.getElementById("file_img").src = this.result;
  19. }
  20. }
  21. }

对于图片上传,也可以先将图片转换为base64进行传输,此时由于传输的图片内容是一段字符串,上传接口可以当做普通post接口处理,当图片传输到后台后,可以在转换为文件实体存储。
考虑到base64转换效率及其本身的大小,会使数据量增多1/3,本方法还是适合于上传内容简单或所占内存较小的文件。

二进制数据上传

比如日常开发中上传excel或者word文档等。
HTML5体系的建立引入了一大堆新的东西,基于XHR2,我们可以直接上传或下载二进制内容,无需像以往一样通过form标签由后端拉取二进制内容。
简单整理下上传逻辑:
1、通过input[type=”file”]标签获取本地文件File对象
2、通过FileReader的readAsArrayBuffer方法将File对象转换为ArrayBuffer
3、创建xhr对象,配置请求信息
4、通过xhr.sendAsBinary直接将文件的ArrayBuffer内容装填至post body后发送

  1. // html
  2. <div id="file"></div>
  3. // javascript
  4. var input = document.getElementById("file"); // input file
  5. input.onchange = function(){
  6. var file = this.files[0];
  7. if(!!file){
  8. var reader = new FileReader();
  9. reader.readAsArrayBuffer(file);
  10. reader.onload = function(){
  11. var binary = this.result;
  12. upload(binary);
  13. }
  14. }
  15. }
  16. //文件上传
  17. function upload(binary){
  18. var xhr = new XMLHttpRequest();
  19. xhr.open("POST", "http://xxxx/opload");
  20. xhr.overrideMimeType("application/octet-stream");
  21. //直接发送二进制数据
  22. if(xhr.sendAsBinary){
  23. xhr.sendAsBinary(binary);
  24. }else{
  25. xhr.send(binary);
  26. }
  27. // 监听变化
  28. xhr.onreadystatechange = function(e){
  29. if(xhr.readyState===4){
  30. if(xhr.status===200){
  31. // 响应成功
  32. }
  33. }
  34. }
  35. }