> Leaf UI 0.8.1 · Package: @ifhover/leaf-ui · Source: 435bab23cad7d343653d9b63b049c0b0601eeefb
> Browser documentation: https://ifhover.github.io/leaf-ui/components/upload.html

> For AI agents: the complete documentation index is available at https://ifhover.github.io/leaf-ui/llms.txt, the full documentation bundle is available at https://ifhover.github.io/leaf-ui/llms-full.txt.

# Upload 文件上传

选择或拖拽文件，查看上传进度。

## 选择与校验


选择文件图片、PDF 或文本 · 最多 5 个文件，每个不超过 5 MB

basic.tsx

复制代码

```tsx lineNumbers file="../../src/examples/upload/basic.tsx"
import { Space, Upload } from '@ifhover/leaf-ui';

export function UploadBasic() {
  return (
    <Space direction="vertical" align="stretch">
      <Upload
        multiple
        accept="image/*,.pdf,.txt"
        maxCount={5}
        maxSize={5 * 1024 * 1024}
        hint="图片、PDF 或文本 · 最多 5 个文件，每个不超过 5 MB"
      />
    </Space>
  );
}
```

展开代码

## 拖拽、进度与取消


此示例在本地模拟上传进度，使用 action 或 customRequest 接入实际上传服务。

点击或拖拽文件到这里仅限图片 · 支持取消与重试

advanced.tsx

复制代码

```tsx lineNumbers file="../../src/examples/upload/advanced.tsx"
import type { UploadRequest } from '@ifhover/leaf-ui';

import { Space, Text, Upload } from '@ifhover/leaf-ui';

const demoRequest = ({ signal, onProgress }: UploadRequest) =>
  new Promise<void>((resolve, reject) => {
    let percent = 0;
    const cleanup = () => {
      clearInterval(timer);
      signal.removeEventListener('abort', abort);
    };
    const abort = () => {
      cleanup();
      reject(new DOMException('Aborted', 'AbortError'));
    };
    const timer = setInterval(() => {
      percent += 12;
      onProgress(percent);
      if (percent >= 100) {
        cleanup();
        resolve();
      }
    }, 180);
    signal.addEventListener('abort', abort, { once: true });
    if (signal.aborted) abort();
  });

export function UploadDrag() {
  return (
    <Space direction="vertical" align="stretch">
      <Text tone="muted">
        此示例在本地模拟上传进度，使用 action 或 customRequest 接入实际上传服务。
      </Text>
      <Upload
        drag
        multiple
        accept="image/*"
        maxCount={4}
        customRequest={demoRequest}
        hint="仅限图片 · 支持取消与重试"
      />
    </Space>
  );
}
```

展开代码

## 使用说明

未配置 action 或 customRequest 时只选择文件，保持待上传状态，可由业务统一提交。action 使用 XMLHttpRequest 报告进度：POST 发送 FormData，PUT 发送文件本身。JSON 响应可提供 url 和 name；customRequest 可返回相同字段。选择和拖拽共用校验，上传支持取消、移除与重试；自定义请求须响应 signal。移除或卸载会取消请求并释放本地预览 URL。服务端仍需进行文件校验。

## 类型

```ts
import type { UploadProps, UploadFile, UploadChangeInfo, UploadRejection, UploadRequest, UploadResult, FileItem } from '@ifhover/leaf-ui';
```

## 手动上传与图片卡片


选择文件

开始上传取消上传

capabilities.tsx

复制代码

```tsx lineNumbers file="../../src/examples/upload/capabilities.tsx"
import { Button, Space, Upload, type UploadHandle } from '@ifhover/leaf-ui';

import { useRef } from 'react';

export function Capabilities() {
  const upload = useRef<UploadHandle>(null);
  return (
    <Space direction="vertical" align="stretch">
      <Upload
        ref={upload}
        autoUpload={false}
        concurrency={2}
        multiple
        accept="image/*"
        listType="picture-card"
        paste
        customRequest={async (request) => {
          await new Promise<void>((resolve, reject) => {
            const timer = setTimeout(resolve, 700);
            request.signal.addEventListener(
              'abort',
              () => {
                clearTimeout(timer);
                reject(request.signal.reason);
              },
              { once: true },
            );
          });
          return {};
        }}
      />
      <Space>
        <Button onClick={() => upload.current?.upload()}>
          {'开始上传'}
        </Button>
        <Button variant="outline" onClick={() => upload.current?.abort()}>
          {'取消上传'}
        </Button>
      </Space>
    </Space>
  );
}
```

展开代码

## UploadProps API

| 属性                | 类型                                                                                                             | 默认值      | 说明                                 |
| ----------------- | -------------------------------------------------------------------------------------------------------------- | -------- | ---------------------------------- |
| `fileList`        | `readonly `[`UploadFile`](#uploadfile-api)`[]`                                                                 | `[]`     | 受控 / 初始文件列表                        |
| `defaultFileList` | `readonly `[`UploadFile`](#uploadfile-api)`[]`                                                                 | `[]`     | 受控 / 初始文件列表                        |
| `onChange`        | `(files: `[`UploadFile`](#uploadfile-api)`[], info: `[`UploadChangeInfo`](#uploadchangeinfo-api)`) => void`    | —        | 列表及上传状态变化                          |
| `accept`          | `string`                                                                                                       | —        | 允许的 MIME 或后缀，如 image/\*,.pdf       |
| `multiple`        | `boolean`                                                                                                      | `false`  | 多文件选择 / 禁用 / 拖拽区域                  |
| `disabled`        | `boolean`                                                                                                      | `false`  | 禁用交互。                              |
| `drag`            | `boolean`                                                                                                      | `false`  | 多文件选择 / 禁用 / 拖拽区域                  |
| `maxCount`        | `number`                                                                                                       | —        | 允许的文件总数                            |
| `maxSize`         | `number`                                                                                                       | —        | 单个文件最大字节数                          |
| `beforeUpload`    | `(file: File) => boolean \| File \| Promise<boolean \| File>`                                                  | —        | 上传前校验，false 拒绝，File 可转换文件          |
| `onReject`        | `(rejections: readonly `[`UploadRejection`](#uploadrejection-api)`[]) => void`                                 | —        | 格式、大小、数量或校验拒绝                      |
| `action`          | `string \| ((file: File) => string \| Promise<string>)`                                                        | —        | 上传地址，未配置时只选择文件                     |
| `method`          | `'POST' \| 'PUT'`                                                                                              | `'POST'` | POST 使用 FormData，PUT 上传文件本身        |
| `headers`         | `Readonly<Record<string, string>>`                                                                             | —        | 请求头                                |
| `data`            | `Readonly<Record<string, string \| Blob>>`                                                                     | —        | POST 的额外表单数据                       |
| `withCredentials` | `boolean`                                                                                                      | `false`  | 跨域发送凭证                             |
| `fieldName`       | `string`                                                                                                       | `'file'` | POST 中的文件字段名                       |
| `customRequest`   | `(request: `[`UploadRequest`](#uploadrequest-api)`) => Promise<`[`UploadResult`](#uploadresult-api)` \| void>` | —        | 自定义异步上传，配合 signal 取消               |
| `onRemove`        | `(file: `[`UploadFile`](#uploadfile-api)`) => boolean \| void \| Promise<boolean> \| Promise<void>`            | —        | 移除前回调，返回 false 保留文件                |
| `showFileList`    | `boolean`                                                                                                      | `true`   | 展示文件列表                             |
| `hint`            | `ReactNode`                                                                                                    | —        | 提示 / 选择按钮或拖拽区域标题                   |
| `children`        | `ReactNode`                                                                                                    | —        | 提示 / 选择按钮或拖拽区域标题                   |
| `name`            | `string`                                                                                                       | —        | 原生 FormData 中的字段名。                 |
| `form`            | `string`                                                                                                       | —        | 关联的原生表单 ID。                        |
| `required`        | `boolean`                                                                                                      | —        | 要求整体值非空，复合控件只校验一次。                 |
| `autoUpload`      | `boolean`                                                                                                      | `true`   | 文件校验通过后自动开始；false 时用 ref.upload()。 |
| `concurrency`     | `number`                                                                                                       | `3`      | 同时进行的上传请求数。                        |
| `directory`       | `boolean`                                                                                                      | —        | 选择目录及其文件；依赖浏览器的目录选择能力。             |
| `paste`           | `boolean`                                                                                                      | —        | 接收剪贴板中的文件。                         |
| `listType`        | `'text' \| 'picture' \| 'picture-card'`                                                                        | `'text'` | 文件列表的展示形式。                         |

## UploadFile API

继承 [`FileItem`](#fileitem-api)，并增加以下字段。

| 属性           | 类型                                                           | 默认值 | 说明                 |
| ------------ | ------------------------------------------------------------ | --- | ------------------ |
| `uid`        | `string`                                                     | 必填  | 必需。唯一标识            |
| `url`        | `string`                                                     | —   | 设置 url。            |
| `name`       | `string`                                                     | —   | 原生 FormData 中的字段名。 |
| `size`       | `number`                                                     | —   | 展示尺寸。              |
| `type`       | `string`                                                     | —   | 设置 type。           |
| `status`     | `'ready' \| 'uploading' \| 'done' \| 'error' \| 'cancelled'` | —   | 设置 status。         |
| `percent`    | `number`                                                     | —   | 完成百分比。             |
| `error`      | `string`                                                     | —   | 设置 error。          |
| `originFile` | `globalThis.File`                                            | —   | 设置 originFile。     |
| `response`   | `unknown`                                                    | —   | 服务端返回的数据           |

## UploadChangeInfo API

| 属性       | 类型                                                                    | 默认值 | 说明      |
| -------- | --------------------------------------------------------------------- | --- | ------- |
| `file`   | [`UploadFile`](#uploadfile-api)                                       | —   | 本次变化的文件 |
| `reason` | `'add' \| 'progress' \| 'success' \| 'error' \| 'remove' \| 'cancel'` | 必填  | 必需。变化原因 |

## UploadRejection API

| 属性        | 类型                                            | 默认值 | 说明         |
| --------- | --------------------------------------------- | --- | ---------- |
| `file`    | `File`                                        | 必填  | 必需。被拒绝的文件  |
| `reason`  | `'type' \| 'size' \| 'count' \| 'validation'` | 必填  | 必需。拒绝原因    |
| `message` | `string`                                      | 必填  | 必需。用户可读的说明 |

## UploadRequest API

| 属性           | 类型                          | 默认值 | 说明                |
| ------------ | --------------------------- | --- | ----------------- |
| `file`       | `File`                      | 必填  | 必需。待上传文件          |
| `signal`     | `AbortSignal`               | 必填  | 必需。取消信号，移除或卸载也会取消 |
| `onProgress` | `(percent: number) => void` | 必填  | 必需。报告上传进度         |

## UploadResult API

| 属性         | 类型        | 默认值 | 说明          |
| ---------- | --------- | --- | ----------- |
| `url`      | `string`  | —   | 上传后的地址 / 名称 |
| `name`     | `string`  | —   | 上传后的地址 / 名称 |
| `response` | `unknown` | —   | 保留业务响应      |

## FileItem API

| 属性           | 类型                                                           | 默认值 | 说明                  |
| ------------ | ------------------------------------------------------------ | --- | ------------------- |
| `uid`        | `string`                                                     | —   | 稳定标识，建议提供           |
| `url`        | `string`                                                     | —   | 文件地址                |
| `name`       | `string`                                                     | —   | 文件名称，默认取 URL 的文件名   |
| `size`       | `number`                                                     | —   | 字节数，可不提供；未提供时不显示大小  |
| `type`       | `string`                                                     | —   | MIME 类型，未提供时根据扩展名识别 |
| `status`     | `'ready' \| 'uploading' \| 'done' \| 'error' \| 'cancelled'` | —   | 上传状态，可不提供           |
| `percent`    | `number`                                                     | —   | 上传进度 0–100          |
| `error`      | `string`                                                     | —   | 失败说明                |
| `originFile` | `File`                                                       | —   | 浏览器选择的原始文件          |

## UploadHandle

| 属性       | 类型                       | 默认值 | 说明                    |
| -------- | ------------------------ | --- | --------------------- |
| `upload` | `(uid?: string) => void` | —   | 必需。开始指定文件或所有待处理文件的上传。 |
| `abort`  | `(uid?: string) => void` | —   | 必需。取消指定文件或所有上传。       |
| `focus`  | `() => void`             | —   | 必需。聚焦控件。              |
