基础文件上传
使用 HTML 的<input type="file" />
元素是实现文件上传最基础的方式。
import React, { useState } from "react";
const FileDemo: React.FC = (props) => {
return (
<input
type="file"
accept="image/*"
// multiple
onChange={async (e) => {
const file = e.target.files?.[0];
console.log("@file", file);
console.log("@文件名字", file?.name);
console.log("@文件大小", (file?.size ?? 0) / 1000 / 1000 + "MB");
}}
/>
);
};
export default FileDemo;
上面代码中:
accept
表示指定接受的文件类型multiple
表示是否允许多文件选择
如果我们希望将得到的File
转为可以显示的DataURL
。则:
const convertFile2DataUrl = (file: File) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
// 处理加载完成事件
reader.onload = (event: ProgressEvent<FileReader>) => {
if (!event.target?.result) {
reject(new Error("Failed to read file"));
return;
}
if (typeof event.target.result !== "string") {
reject(new Error("Invalid result type"));
return;
}
resolve(event.target.result);
};
// 处理错误
reader.onerror = () => {
reject(new Error("Error reading file: " + reader.error?.message));
};
// 处理中止
reader.onabort = () => {
reject(new Error("File reading aborted"));
};
try {
reader.readAsDataURL(file);
} catch (error) {
reject(
new Error("Failed to start reading file: " + (error as Error).message)
);
}
});
};
动态文件上传
动态文件上传,表示我们随时动态创建或者引用一个隐藏在页面上的input
元素。这样我们就是可以随时动态的控制文件上传,并可以更容易的定制上传组件的样式。
import React, { useState } from "react";
const FileDemo = () => {
const inputRef = React.useRef<HTMLInputElement>(null);
const handleUpload = async () => {
const onChange = async (e: Event) => {
const file = (e.target as HTMLInputElement).files?.[0];
console.log("@file", file);
console.log("@文件名字", file?.name);
console.log("@文件大小", (file?.size ?? 0) / 1000 / 1000 + "MB");
};
if (!inputRef.current) return;
inputRef.current.onchange = onChange;
inputRef.current?.click();
// 或
// const input = document.createElement("input");
// input.type = "file";
// input.accept = "image/*";
// input.onchange = onChange;
// input.click();
};
return (
<div>
<div
className="bg-yellow-400 cursor-pointer p-2 rounded"
onClick={handleUpload}
>
点击上传文件
</div>
<input
ref={inputRef}
type="file"
accept="image/*"
style={{ display: "none" }}
/>
</div>
);
};
export default FileDemo;
上传进度监控
上传文件监控我们是基于 axios 实现的。
axios.post("/api", file, {
onUploadProgress: progressEvent => {
if (progressEvent.total) {
console.log(progressEvent.loaded, progressEvent.total);
}
},
});