外观
UUpload:上传文件并维护 URL
UUpload 将上传结果转换为 URL model。文件校验、上传请求和存储策略分别配置;移除预览项只修改 model,不会删除服务器文件。
推荐示例:显式上传契约
下面定义一个 示例应用接口 POST /api/files:multipart 字段 file,成功返回 { url: string },失败返回非 2xx。此 endpoint 不是 uAdmin 内置后端,需由应用实现或替换。请求函数显式检查状态,避免把业务失败当成上传成功。
vue
<script setup lang="ts">
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElMessage, type UploadRequestOptions } from 'element-plus'
import { UUpload } from '@uadmin/ui'
const props = defineProps<{ authorization?: string }>()
const urls = ref<string[]>([])
const { t } = useI18n({
useScope: 'local',
messages: {
'zh-CN': {
hint: '最多 3 张图片,每张不超过 5 MB',
failed: '上传失败',
invalid: '上传响应缺少文件地址',
},
'en-US': {
hint: 'Up to 3 images, 5 MB each',
failed: 'Upload failed',
invalid: 'Upload response has no URL',
},
},
})
async function upload(request: UploadRequestOptions): Promise<{ url: string }> {
const body = new FormData()
body.append('file', request.file)
const response = await fetch('/api/files', {
method: 'POST',
body,
headers: props.authorization ? { Authorization: props.authorization } : undefined,
})
if (!response.ok) throw new Error(t('failed'))
const result: unknown = await response.json()
if (
!result ||
typeof result !== 'object' ||
!('url' in result) ||
typeof result.url !== 'string' ||
!result.url
)
throw new Error(t('invalid'))
return { url: result.url }
}
function showError(error: Error) {
ElMessage.error(error.message)
}
</script>
<template>
<UUpload
v-model="urls"
mode="media"
:max-count="3"
:max-size="5"
multiple
:custom-request="upload"
@error="showError"
>
<template #tip>{{ t('hint') }}</template>
</UUpload>
</template>不要手工设置 multipart Content-Type;浏览器需要为 FormData 添加 boundary。
请求选择顺序与内置请求
优先级为:组件 customRequest → 注入的 UploadRequestInjectKey → 内置 fetch。前两者返回 Promise<{ url: string }>,自行处理鉴权、额外字段和错误。
内置 fetch 向 action POST FormData,响应读取 data.url,例如 { "data": { "url": "/files/a.png" } };它不走 @uadmin/app 的 Axios 拦截器,也不自动解开其它信封。当前内置路径没有检查 response.ok 或业务 code,复杂后端建议使用上面的 customRequest。
UploadTokenInjectKey 返回完整 Authorization 值(如 Bearer ...),仅内置请求会使用它。应用级处理器可通过 app.provide(UploadRequestInjectKey, upload) 安装;显式组件处理器始终优先。
Props
| Prop | 类型 | 默认 / 行为 |
|---|---|---|
modelValue | string | string[] | URL 或 URL 数组 |
mode | 'media' | 'file' | 'avatar' | 'media';media/avatar 都是 picture-card 列表 |
action | string | '/api/upload',仅内置请求使用 |
accept | string | media/avatar 为 image/*,file 不限制 |
maxSize | number | 10,单位 MB;0 关闭大小校验 |
maxCount | number | 9 |
multiple | boolean | false;是否允许一次选择多个文件 |
name | string | 'file',内置 FormData 字段名 |
extraData | Record<string, string | number> | 内置请求额外表单字段 |
withCredentials | boolean | false;true 用 include,否则 same-origin |
beforeUpload | (file: File) => boolean | Promise<boolean> | 大小校验通过后执行;false 或抛异常阻止上传 |
customRequest | (req: UploadRequestOptions) => Promise<{ url: string }> | 替换上传过程 |
Model、事件与插槽
只要 multiple=true 或 maxCount>1,更新值就是数组。 默认 maxCount=9,所以即使 multiple=false 也不要绑定字符串 ref。单头像需明确设置:
vue
<UUpload v-model="avatarUrl" mode="avatar" :max-count="1" :multiple="false" />这里 avatarUrl 是 ref('')。avatar 模式不包含图片裁剪;超出一张时触发 exceed,不会自动替换旧文件。
| Event / Slot | 参数 / 用途 |
|---|---|
update:modelValue | string | string[] |
success | (url: string, file: File) |
error | (error: Error, file: File) |
exceed | 无参数,超过数量限制 |
default 插槽 | 替换选择按钮/加号 |
tip 插槽 | 上传提示 |
accept 是浏览器选取提示,不是内容安全校验;服务器仍需校验类型与大小。Blob URL 只适合当前浏览器会话,需要刷新后保留时存储文件并重建 URL,不能把 blob 地址当永久下载链接。