React 中封装一个 FileReader 组件

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React 中封装一个 FileReader 组件相关的知识,希望对你有一定的参考价值。

React 中封装一个 FileReader 组件

最近有一个业务需求需要在页面内实现一个文件上传的功能,本来想找第三方库实现的,后来发现 html5 中新提供了一个 FileReader API 就能实现功能,因此就想着试试看自己写一个组件。

API 介绍

FileReader 有 6 个事件,以下是 MDN 中的描述:

事件描述
abort当文件读取放弃时调用,如调用 FileReader.abort()
error当文件读取出错时被调用
load当文件成功被读取时调用
loadend当文件读取结束时被调用
loadstart当文件读取开始时被调用
progress文件读取过程中随机调用 \\newline ProgressEvent 本身也有三个属性可以用来展示当前加载状态:lengthComputable, loaded, 和 total

几个事件的触发都可以通过 addEventListener 或者直接绑定对应事件完成触发:

addEventListener("progress", (event) => );

onprogress = (event) => ;

FileReader 中包含 3 个可读属性:

属性描述
FileReader.error一个用来描述文件读取时发生异常的 DOMException
FileReader.readyState表示文件读取的状态 \\newline 0 为实例已创建,但是还没开始读取 \\newline 1 为已经开始读取 \\newline 2 为操作已完成
FileReader.result读完的文件,格式为对应的调用函数

然后这是读取文件的方法:

方法参数描述
abortnone中断读取 \\newline 调用后 FileReader.readyState 会变成 2,即 DONE
readAsArrayBufferfile or blob将文件读取为 ArrayBuffer,适合处理图片这样的文件 \\newline 这是一个新一点的 API,所以不是所有的浏览器都会支持,向下兼容的 API 为 readAsBinaryString()
readAsDataURLfile or blob将文件读取为 DataURL(base64 encoded string)
readAsTextfile or blob, [encoding]将文件读取为文本,这个是最常操作的部分了,encoding 默认为 UTF-8

了解了基础的 API,那么就能封装一个简易的文件上传了

React 代码

这里分为两个组件写,组件 1 就是渲染部分:

添加了 onclick 事件去重新设置 event.target.value 之后,onChange 能够获取事件的变化,否则没有办法使用该组件重复上传文件。

import  useState  from "react";
import  readUploadFile  from "./fileReaderHelper";
import "./styles.css";

export default function App() 
  const [img, setImg] = useState("");

  const changeHandler = async (e) => 
    const res = await readUploadFile(e);
    console.log(res);
    setImg(res);
  ;

  return (
    <>
      <input
        type="file"
        onChange=changeHandler
        onClick=(e) => (e.target.value = null)
      />
      <p>Preview</p>
      <img src=img alt="sample img" />
    </>
  );

组件 2 为 UploadHelper:

做一个完整的组件其实需求部分挺多的,比如说如果需求包含上传图片、文档、视频、音频等,这里可能需要使用正则,根据上传的文件去调用对应的 API。

export const readUploadFile = (e) => 
  const reader = new FileReader();

  return new Promise((res, rej) => 
    reader.addEventListener("error", () => 
      reader.abort();
      rej(new Error("Problem reading file"));
    );

    reader.addEventListener("progress", (e) => 
      console.log(e.loaded + " has been transferred");
      console.log("file size: " + e.total);
      console.log(e.lengthComputable);
    );

    reader.addEventListener("load", () => 
      res(reader.result);
    );

    reader.addEventListener("loadstart", () => 
      // add some spinner
    );

    reader.addEventListener("loadend", () => 
      // remove spinner
    );

    reader.readAsDataURL(e.target.files[0]);
  );
;

整体代码来说比较简单,因为 FileReader 是异步函数,因此在返回的时候需要包装成一个 Promise 去实现。另外 FileReader 在 Web Workers 中也有实现,因此也可以实现非阻塞式上传。

效果图:

以上是关于React 中封装一个 FileReader 组件的主要内容,如果未能解决你的问题,请参考以下文章

如何在清理函数中的 React js 中执行 fileReader.removeEventListener

react--封装上传组件

让开!!!谁也别拦着我封装React组件!

谈一谈我对react中组件的理解

React -- 组件封装&props

react初探之父子组件通信封装公共组件