File / FileReader应用及不同格式之间的相互转化

534 阅读5分钟

File

File就是文件,继承自Blob,所有可以使用 Blob 对象的场合都可以使用它。也是二进制对象,也有自己特有的属性和方法

通常用在<input type="file">选择的FileList对象,或者是使用拖拽操作产生的的DataTransfer对象。

构造函数创建File对象

var myFile = new File(array, name[, options]);
  • array: 一堆数据构成的数组
  • name: 文件名
  • options: 设置一些属性,type属性、lastModified

示例:

const myFile = new File(['leo1', 'leo2'], 'leo.txt', {type: 'text/plain'});

属性

  • name: 文件名
  • size: 文件大小
  • lastModified: 最后修改时间(时间戳)
  • lastModifiedDate: 最后修改时间Data对象
  • type: MIME类型

方法

继承自Blob的slice方法

Blob.slice([start, end, contentType)
  • start:分割起始点
  • end: 分割终点
  • contentType:新的MIME类型

FileList

对于type="file"的input元素,用户选择文件上传后会生成一个FileList对象

FileList 对象是一个类数组对象,每个成员都是一个 File 实例

获取FileList

// <input id="fileItem" type="file">
const file = document.getElementById('fileItem').files;

FileList对象

{
  0: {
    lastModified: 1482289489971
    lastModifiedDate: Wed Dec 21 2016 11:04:49 GMT+0800,
    name: "index.html"
    size: 1325
    type: "text/html"
  },
  1: {
    ...
  },
  length: 2
}

FileReader

简单理解,就是用于读取 File 对象或 Blob 对象所包含的文件内容。

FileReader对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

其中File对象可以是来自用户在一个<input>元素上选择文件后返回的FileList对象,也可以来自拖放操作生成的 DataTransfer对象,还可以是来自在一个HTMLCanvasElement上执行mozGetAsFile()方法后返回结果。

构造函数

let reader = new FileReader();

实例属性

  • FileReader.error : 表示在读取文件时发生的错误。只读

  • FileReader.readyState : 整数,表示读取文件时的当前状态。只读

    • 共有三种状态:
      • 0 : EMPTY,表示尚未加载任何数据;
      • 1 : LOADING,表示数据正在加载;
      • 2 : DONE,表示加载完成;
  • FileReader.result 读取完成后的文件内容。只读,仅在读取操作完成后才有效,返回的数据格式取决于使用哪个方法来启动读取操作。

方法

FileReader接口有4个方法,其中3个用来读取文件,另一个用来中断读取。无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中。

方法名参数描述
readAsBinaryStringfile将文件读取为二进制编码
readAsTextfile,[encoding]将文件读取为文本
readAsDataURLfile将文件读取为 Data URL 格式(Base64 编码)的字符串
abort(none)终止读取操作,readyState 属性将变成2

readAsDataURL可用于读取图片文件,返回的字符串可以用于元素的 src 属性。

注意,这个字符串不能直接进行 Base64 解码,必须把前缀 data:/;base64 ,从字符串里删除以后,再进行解码。

事件处理程序

事件调用时机
onabort当读取操作被中止时调用
onerror当读取操作发生错误时调用
onload当读取操作成功完成时调用
onloadend当读取操作完成时调用,不管是成功还是失败.该处理程序在onload或者onerror之后调用
onloadstart当读取操作将要开始之前调用
onprogress在读取数据过程中周期性调用

读取文本

我们从FileList中可以获取文件名、修改时间、大小和文件类型等信息,文件内容也是包含在里面的,不过需要FileReader的读取文件方法才能获取,对于纯文本,我们使用readAsText方法,如下:

//FileReader读取文件内容
var reader = new FileReader();
reader.readAsText(files[0], 'UTF-8');
reader.onload = function (e) {
    // urlData就是对应的文件内容
    var urlData = this.result;
};

图片预览

<form>
    <input type="file" id="file1" name="file1" />
    <input type="submit" />
    <img id="img1" src=""/>
</form>
//选择图片后,预览图片			
document.getElementById("file1").onchange=function(){
    //1 创建文件读取对象
    var reader=new FileReader();

    //文件存储在file表单元素的files属性中,它是一个数组
    //没有返回值,但是读取完毕后,将读取结果存储在对象的result中
    var fil=document.getElementById("file1").files;
    reader.readAsDataURL(fil[0]);

    //当读取成功后触发
    reader.onload=function(){
        document.getElementById("img1").src=reader.result;
    };
};

前端读取excel文件

核心代码:

var reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = function (evt) {
   //当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
   var data = evt.target.result,
}

使用js-xlsx,来读取文件内容

npm install js-xlsx

在reader.onload函数中

reader.onload = function (evt) {
    //当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
    try {
      var data = evt.target.result,
          workbook = XLSX.read(data, {
              type: 'binary'
          }), // 以二进制流方式读取得到整份excel表格对象
          buildings = []; // 存储获取到的数据
          var fromTo = '';
          // 遍历每张表读取
          for (var sheet in workbook.Sheets) {
              if (workbook.Sheets.hasOwnProperty(sheet)) {
                  fromTo = workbook.Sheets[sheet]['!ref'];
                  buildings = buildings.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet]));
                  // break; // 如果只取第一张sheet表,就取消注释这行
              }
          }
          let fileRows = buildings.length - 1;//表格内容行数,减去表头的一行
          
  } catch (e) {
      console.log('文件类型不正确',e);
      return;
  }
}

代码中workbook对象可以获取到文件的详细信息

文件互相转换

  1. File文件转换为Blob对象
let aBlob = new Blob([file], {type: file.type})
  1. Blob转换为File
let files = new window.File([this.blob], file.name, {type: file.type})
  1. File / Blob文件转换为base64
function blobToDataURL(blob, callback) {
    let a = new FileReader();
    a.onload = function (e) { 
      callback(e.target.result); 
    }
    a.readAsDataURL(blob);
}
  1. 图片url转换为base64
img2base64(imgUrl) {
  let image = new Image()
  image.src = imgUrl
  return new Promise((resolve) => {
    image.onload = () => {
      let canvas = document.createElement('canvas')
      canvas.width = image.width
      canvas.height = image.height
      var context = canvas.getContext('2d')
      context.drawImage(image, 0, 0, image.width, image.height)
      let dataUrl = canvas.toDataURL('image/png')
      resolve(dataUrl)
    }
  })
},
  1. base64转Blob
function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
}
  1. base64转File
 function dataURLtoFile(dataurl, filename) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, {type:mime});
}

参考文章