文件上传 Upload
Upload 组件封装了原生 <input type="file">,支持三种上传模式(头像 / 图片 / 文件)、拖拽上传、上传预览、自定义上传请求等能力。
组件内部只负责文件选择与 UI 展示,不强制绑定请求方式,可通过 uploadFn 完全自定义上传逻辑。
📦 引入方式
import { Upload } from '@itera-web/react-ui-upload';
🧩 使用示例
- 示例
- 源码
import React from 'react';
import { Upload } from '@itera-web/react-ui-upload';
import { message } from '@itera-web/utils-message';
export default function DemoUpload() {
const handleFile = async (file) => {
try {
await file.arrayBuffer();
} catch (err) {
message.error('文档解析失败', err);
}
};
return (
<div className="flex flex-col gap-4">
<Upload
accept=".png,.jpg,.jpeg"
className="w-[200px] h-[200px] rounded-full"
desc="上传头像"
onFileSelect={(_, res) => {
console.log(res?.data?.fullurl, res);
}}
type="avatar"
// uploadFn={requestUpload} 自定义上传函数 默认ContentType: 'multipart/form-data' 组件内上传参数 { file: selectedFile }
/>
<Upload
accept=".png,.jpg,.jpeg"
className="w-[400px] h-[200px]"
desc="上传图片"
onFileSelect={(_, res) => {
console.log(res?.data?.fullurl, res);
}}
type="image"
// uploadFn={requestUpload} 自定义上传函数 默认ContentType: 'multipart/form-data' 组件内上传参数 { file: selectedFile }
/>
<Upload accept=".docx" className="h-[200px]" desc="请上传 docx 文件" drag onFileSelect={handleFile} />
</div>
);
}
✨ 功能特性
-
支持三种上传模式:
avatar:圆形头像上传,支持悬停删除按钮、点击查看大图image:普通图片上传,支持预览、查看大图file:文件上传(任意类型),支持拖拽区域
-
支持 拖拽上传 drag
-
支持文件预览(图片类型自动预览)
-
支持设置
accept限制文件类型 -
提供
uploadFn完全自定义上传流程 -
内置上传中状态、成功/错误提示
-
支持点击删除已上传文件
-
支持受控回填
value,用于回显图片/文件(如编辑页面)
📐 Props 属性说明(完整)
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| type | 'avatar' | 'image' | 'file' | 'file' | 上传类型,不同类型 UI 与交互不同 |
| drag | boolean | false | 是否开启拖拽上传 |
| accept | string | '' | 允许选择的文件类型,等同于 <input accept> |
| desc | string | '' | 描述文字,例如“点击上传” |
| value | string | undefined | 外部传入的预览图片地址(受控模式) |
| id | string | undefined | input 的 id,用于表单或自动化测试 |
| className | string | '' | 自定义样式类 |
| uploadFn | ({ file }: { file: File }) => Promise<any> | () => void 0 | 自定义上传逻辑,返回的值会透传到 onFileSelect |
| onFileSelect | (file: File | null, response?: any) => void | () => void 0 | 选择文件后的回调,删除时 file = null |
📤 onFileSelect 回调说明
onFileSelect?: (file: File | null, response?: any) => void;
触发时机:
| 场景 | file | response |
|---|---|---|
| 选择文件成功 | File | uploadFn 返回结果 |
| 上传失败 | File | undefined |
| 删除文件 | null | null |
🔧 uploadFn 自定义上传函数说明(非常重要)
uploadFn 会在选择文件后自动调用:
const result = await uploadFn({ file });
用于支持任何上传方式:
- axios form-data
- fetch
- OSS / Qiniu / Cos 直传
- 手写流上传
示例:
const uploadFn = async ({ file }) => {
const form = new FormData();
form.append('file', file);
return axios.post('/api/upload', form);
};
你返回的内容会在上传成功后传入:
onFileSelect(selectedFile, result);
🖼️ 各上传类型行为说明
- type = "avatar"
- 显示为圆形区域
- 有预览能力
- 悬停会出现删除按钮
- 点击图片可查看大图
- 无描述文案(可通过 desc 覆盖)
- type = "image"
- 固定高 h-24,宽度自适应父容器
- 鼠标悬停后出现查看与删除按钮
- 点击图片可查看大图
- type = "file"
- 不显示预览(非图片)
- 可显示文件名
- 支持拖拽上传区域 UI
🖱️ 拖拽上传 drag 说明
当 drag= 时:
- 拖入区域高亮(蓝色边框)
- 放置后触发上传
- 行为等同于点击选择文件
支持拖入多个文件,但只取第一个:
const droppedFile = e.dataTransfer.files[0];
🔄 上传流程说明(组件内部逻辑)
流程图:
选择文件 或 拖拽文件
↓
显示预览(若为图片)
↓
执行 uploadFn({ file })
↓
成功 → 显示上传成功 + 回调 onFileSelect(file, result)
失败 → 显示错误提示 + 回调 onFileSelect(file, undefined)
↓
自动清空 input.value 允许重复上传同一文件
🗑️ 删除文件行为说明
点击删除按钮:
- 清空预览
- 清空 input.value
- file 设置为 null
- 触发 onFileSelect(null, null)
🔍 大图预览说明
支持点击预览图查看大图:
{
showPreview && preview && (
<div className="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center">
<img src={preview} className="max-h-[90%] max-w-[90%]" />
</div>
);
}
点击遮罩关闭。
🎛️ 外部受控回显 value
支持传入网络图片地址:
<Upload type="image" value="https://xxx.com/a.png" />
会自动更新 preview。