在网页中读取本地文件

3,137 阅读2分钟

最近为我们的 Web 应用实现了一个小功能,读取本地 CSV 文件,解析成 JSON 数据展示,在以前要实现这样的功能往往需要服务端的介入,将文件上传到服务器,再由服务器将内容返回给前端,但是现在我们可以利用 File 和 FileReader API 来完成这样的事情。File 用来描述一个文件对象,提供给 FileReader 使用。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div>
    <input
      accept="text/csv"
      id="contained"
      name="csvfile"
      type="file"
    />
  </div>
  <script>
    var contained = document.querySelector("#contained");
    function handleUpload(e){
      console.log(e.target.files);
    }
    contained.addEventListener("change", handleUpload);
  </script>
</body>
</html>

files 是一个 FileList ,下标元素为 0 的元素则是我们要获取的 File 对象,你可以通过这些属性大概了解到它包含哪些,比如 name,size ,type等等。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div>
    <input
      accept="text/csv"
      id="contained"
      name="csvfile"
      type="file"
    />
  </div>
  <script>
    var contained = document.querySelector("#contained");
    var fileReader = new FileReader();
    fileReader.onload = function(e){
      console.log(e.target)
    }
    function handleUpload(e){
      var file = e.target.files[0];
      fileReader.readAsText(file);
    }
    contained.addEventListener("change", handleUpload);
  </script>
</body>
</html>

然后我们 new 一个 FileReader 对象,监听 onload 事件,通过 e.target.result 来获取本地读书的内容,不过我们还要通过 readAsText 来驱动,并将 File 对象传递给它。当然了,FileReader 也提供了几个状态让你在进行时的时候去处理,readyState 很好的完成了这项工作,正常情况下,我个人会直接读取 ArrayBuffer ,二进制的数据比字符串更容易操作或切割,如果你了解 分片 的概念的话,我们很容易的去操作它。要读取 ArrayBuffer 需要使用 readAsArrayBuffer

可以说,这是一组非常简单的 API ,但是有一些 注意事项 需要我们去克服,就是读取文件之前,我们能前置的知道文件的编码格式,比如 utf-8,每一个 readAs... 系列的 API 都有第二个参数,这个参数用于指明使用什么样的编码来读取。但很遗憾,这些 API 中没有获取文件编码的 API ,如果你的文件本身是一个 国标 的编码,如果我们按正常的默认值 utf-8 来读取,是会读取上来一堆乱码,无法解决的,但是如果你能前置的知道这些 GB 的编码,在使用 readAs... API 读取时可以传递第二个参数来使用正确的编码去读取,(默认 UTF-8编码)这可能是使用它唯一需要注意的地方。