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 | 读完的文件,格式为对应的调用函数 |
然后这是读取文件的方法:
方法 | 参数 | 描述 |
---|---|---|
abort | none | 中断读取
\\newline
调用后 FileReader.readyState 会变成 2 ,即 DONE |
readAsArrayBuffer | file or blob | 将文件读取为 ArrayBuffer,适合处理图片这样的文件
\\newline
这是一个新一点的 API,所以不是所有的浏览器都会支持,向下兼容的 API 为 readAsBinaryString() |
readAsDataURL | file or blob | 将文件读取为 DataURL(base64 encoded string) |
readAsText | file 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 组件的主要内容,如果未能解决你的问题,请参考以下文章