如何在 React 项目中使用 FileReader 读取本地文件
FileReader 是什么
FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。
FileReader 的基本用法
此处展示读取本地文本文件的示例
<--读取本地文件-->
<input type="file" onChange={handleFileReader} />
const handleFileReader = async (e) => {
try {
// 获取文件
const file = e.target.files[0];
// 实例化 FileReader对象
const reader = new FileReader();
reader.onload = function (e) {
// 在onload函数中获取最后的内容
setFileContent(e.target.result as string);
};
// 调用readerAsText方法读取文本
reader.readAsText(file);
} catch (error) {
console.log(error)
}
};
如何在 React 中使用
在 react 中我们可以封装成一个 hook,使其具有复用性,和提供易用性
创建<input type="file" />示例获取本地文件
由于在实际使用的时候用户其实并不想要在document上挂载<input type="file" /> dom示例,因此我们可以利用createElement在内存中创建该dom示例只利用他的能力而不挂载到document文档
const createFileInput = () => {
const $fileInput = document.createElement("input");
$fileInput.type = "file";
return $fileInput;
};
设计 hook 的入参和出参
在该hook中用户不需要传入任何额外的入参
出参包括文件的文本内容、读取错误的错误信息、是否正在读取中的状态和触发用户选择本地文件的方法
具体的 ts 定义如下
export type Result = {
// 文件的文本内容
fileContent: string;
// 是否正在读取中的状态
isReading: boolean;
// 读取错误的错误信息
error: any;
trigger: () => void;
};
核心代码编写
完整代码
import React, { useState, useRef } from "react";
export type Result = {
fileContent: string;
isReading: boolean;
error: any;
trigger: () => void;
};
const createFileInput = () => {
const $fileInput = document.createElement("input");
$fileInput.type = "file";
return $fileInput;
};
const useTextFileReader = (): Result => {
const [fileContent, setFileContent] = useState<string>("");
const [isReading, setIsReading] = useState<boolean>(false);
const [error, setError] = useState<any>(null);
const fileInputRef = useRef(createFileInput());
const handleFileReader = async (e) => {
setIsReading(true);
try {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = function (e) {
setFileContent(e.target.result as string);
};
reader.readAsText(file);
} catch (error) {
setError(error);
} finally {
setIsReading(false);
}
};
fileInputRef.current.onchange = handleFileReader;
const trigger = () => {
fileInputRef.current.click();
};
return {
fileContent,
isReading,
error,
trigger,
};
};
export default useTextFileReader;