File API

FileAPI(文件API)为Web开发人员提供一种安全的方式,以便在客户端访问用户计算机中的文件,并更好地对这些文件执行操作

File API在表单中的文件输入字段的基础上,又添加了一些直接访问文件信息的接口。HTML5在DOM中为文件输入元素添加了一个files集合。在通过文件输入字段选择了一或多个文件时,files集合中将包含一组File对象,每个File对象对应着一个文件。每个File对象都有下列只读属性

name:本地文件系统中的文件名

size:文件的字节大小

type:字符串,文件的MIME类型

lastModifiedDate:字符串,文件上一次被修改的时间
<button id="btn">btn</button>
<input type="file" id="upload" multiple>
<script>
 upload.onchange = function(e) {
   var files = e.target.files;
   for (var i = 0; i < files.length; i++) {
     var file = files[i];
     console.log(file);
   }
 }
 </script>

FileReader

FileReader可以读取文件中的数据

使用FileReader()构造函数来创建一个FileReader对象

var reader = new FileReader();

属性

error:表示在读取文件时发生的错误(只读)

readyState:表明FileReader对象的当前状态,值为状态常量中的一个(只读),状态常量有以下三个

常量名     值    描述
EMPTY      0    还没有加载任何数据
LOADING    1    数据正在被加载
DONE       2    已完成全部的读取请求

result:表示读取到的文件内容,这个属性只在读取操作完成之后才有效,并且数据的格式取决于读取操作是由哪个方法发起的(只读)

方法

FileReader类型实现的是一种异步文件读取机制,类似于XMLHttpRequest,区别只是它读取的是文件系统,而不是远程服务器。

为了读取文件中的数据,FileReader提供了如下几个方法

abort(): 终止读取操作

readAsText(file或Blob,encoding):以纯文本形式读取File或Blob对象的内容,将读取到的文本保存在result属性中。第二个参数(可选)用于指定编码类型,默认为UTF-8

readAsDataURL(file或Blob):读取File或Blob对象的内容,并将文件以数据URI(进行Base64编码)的形式保存在result属性中

readAsBinaryString(file或Blob):读取File或Blob对象的内容,并将一个字符串保存在result属性中,字符串中的每个字符表示一字节

readAsArrayBuffer(file或Blob):读取File或Blob对象的内容,并将一个包含文件内容的ArrayBuffer保存在result属性中

事件

类似于XMLHttpRequest对象,FileReader也提供了几个事件

onabort:当读取操作被中止时调用

onerror:当读取操作发生错误时调用

onload:当读取操作成功完成时调用

onloadend:当读取操作完成时调用,不管是成功还是失败。该处理程序在onload或者onerror之后调用

onloadstart:当读取操作将要开始之前调用

onprogress:在读取数据过程中周期性调用

示例

<button id="btn">btn</button>
<input type="file" id="upload" style="display:none">
<script>

btn.onclick = function() {
  upload.click()
}
upload.onchange = function(e) {
  var render = new FileReader();
  render.readAsText(e.target.files[0]);
  reader.onloadstart = function(e) {
    console.log('[loadstart]readyState:' + reader.readyState + ';result:' + reader.result);
  }
  reader.onload = function(e) {
    console.log('[load]readyState:' + reader.readyState + ';result:' + reader.result);
  }
  reader.onloadend = function(e) {
    console.log('[loadend]readyState:' + reader.readyState + ';result:' + reader.result);
  }
  reader.onprogress = function(e) {
    console.log('[progress]readyState:' + reader.readyState + ';result:' + reader.result);
  }
}

// [loadstart]readyState:1;result:
// [progress]readyState:1;result:hello world
// [load]readyState:2;result:hello world
// [loadend]readyState:2;result:hello world
</script>

读取文件时,首先触发loadstart事件,此时readyState为1,result为空。接着,每过50ms左右,就会触发一次progress事件,通过事件对象可以获得与XHR的progress事件相同的信息(属性):lengthComputable、loaded和total。当文件读取完成时,触发load事件,此时的readyState为2,result为文件内容。

如果触发了error事件,就不会发生load事件。触发error事件时,相关的信息将保存到FileReader的error属性中。这个属性中将保存一个对象,该对象只有一个属性code,即错误码。这个错误码是1表示未找到文件,是2表示安全性错误,是3表示读取中断,是4表示文件不可读,是5表示编码错误

如果想中断读取过程,可以调用abort()方法,这样就会触发abort事件。

在触发load、error或abort事件后,会触发另一个事件loadend。loadend事件发生就意味着已经读取完整个文件,或者读取时发生了错误,或者读取过程被中断

缩略图

使用FileReader对象的readAsDataURL()方法完成对文件的读取,再通过File对象的type属性筛选出图片

示例

<img src="https://cdn.86886.wang/blog/1533885924628.jpg" alt="preview" id="previewImg">
  <p id="imgName"></p>
  <input type="file" id="upload" style="display:none" accept="image/gif,image/jpeg,image/jpg,image/png,image/x-icon">
  <button id="btn">btn</button>
  <script>
  btn.onclick = function() {
    upload.click()
  }
  upload.onchange = function(e) {
    var file = e.target.files[0];
    if(file) {
      if(/image/.test(file.type)) {
        var render = new FileReader();
        render.readAsDataURL(file);
        render.onload = function() {
          previewImg.src = render.result;
          imgName.innerHTML = file.name;
        }
      }
    }
  }
</script>

文件进度

使用onprogress事件的loaded和total属性,可以实现文件进度显示

<input id="upload" type="file" style="display:none">
<button id="btn">选择文件</button>
<div id="fileData"></div>
<script>
btn.onclick = function() { upload.click(); }
upload.onchange = function() {
  var file = upload.files[0];
  if (file) {
    var reader = new FileReader();
    reader.readAsText(file);
    reader.onprogress = function(e) {
      fileData.innerHTML = '文件进度为:' + e.loaded + '/' + e.total;
    }
  }
}
</script>

文件上传

方式一

传统方式,使用表单提交实现文件上传。必须在<form>元素中将enctype设置为"multipart/form-data",将method设置为"post"。另外,需要在<form>表单中设置一个hidden类型的input框,其中name值为MAX_FILE_SIZE的隐藏值域,通过设置其value值限制上传文件的大小,单位bytes

<form action="pp.php" method="post" enctype="multipart/form-data">
    <input type="hidden" name="MAX_FILE_SIZE" value="1048576">
    <input type="file" name="file1">
    <button>上传文件</button>
</form>

方式二

使用FormData实现文件上传

创建一个FormData()对象,调用append()方法并传入相应的File对象作为参数。然后,再把FormData对象传递给XHR的send()方法

<input id="upload" type="file" style="display:none">
<button id="btn">选择文件</button>
<script>
btn.onclick = function() { upload.click(); }
upload.onchange = function() {
  var data = new FormData(),
    file = upload.files[0],
    xhr = new XMLHttpRequest();

  data.append('file', file);
  xhr.onreadystatechange = function() {
    if(xhr.readyState == 4) {
      if(xhr.status == 200) {
        console.log(xhr.responseText)
      }
    }
  }
  xhr.open('post', '/api/test', true);
  xhr.send(data);
}
</script>

注意: IE9-浏览器不支持使用FormData()上传文件

方式三

使用File API实现文件上传,通过File API传送二进制文件

<input id="upload" type="file" style="display:none">
  <button id="btn">选择文件</button>
  <script>
  btn.onclick = function() { upload.click(); }
  upload.onchange = function() {
    var file = upload.files[0],
      xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if(xhr.readyState == 4) {
        if(xhr.status == 200) {
          console.log(xhr.responseText)
        }
      }
    }
    xhr.open('post', '/api/test', true);
    xhr.setRequestHeader("content-type",file.type);
    xhr.send(file);
  }
  </script>

注意: IE9-浏览器不支持

posted @ 2021-09-29 14:22  wmui  阅读(122)  评论(0编辑  收藏  举报