Skip to content
uAdmin

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类型默认 / 行为
modelValuestring | string[]URL 或 URL 数组
mode'media' | 'file' | 'avatar''media';media/avatar 都是 picture-card 列表
actionstring'/api/upload',仅内置请求使用
acceptstringmedia/avatar 为 image/*,file 不限制
maxSizenumber10,单位 MB;0 关闭大小校验
maxCountnumber9
multiplebooleanfalse;是否允许一次选择多个文件
namestring'file',内置 FormData 字段名
extraDataRecord<string, string | number>内置请求额外表单字段
withCredentialsbooleanfalse;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:modelValuestring | string[]
success(url: string, file: File)
error(error: Error, file: File)
exceed无参数,超过数量限制
default 插槽替换选择按钮/加号
tip 插槽上传提示

accept 是浏览器选取提示,不是内容安全校验;服务器仍需校验类型与大小。Blob URL 只适合当前浏览器会话,需要刷新后保留时存储文件并重建 URL,不能把 blob 地址当永久下载链接。

相关:图标按钮 · 富文本中的图片

Vue 3 · TypeScript · Element Plus