Skip to content

Upload 上传

文件上传。支持点击与拖拽、单个与批量、自动与手动提交。

基础用法

将文件拖到此处,或 点击选择支持单个或批量上传,单张不超过 5MB
vue
<script setup>
import { ref } from 'vue'
const files = ref([])
</script>

<template>
  <SrUpload
    v-model="files"
    action="/api/upload"
    accept="image/*"
    :max-size="5"
    tip="支持单个或批量上传,单张不超过 5MB"
  />
</template>

acceptmax-size 不是安全措施——它们只是提前拦下明显的错误。 真正的校验必须在服务端做:客户端传什么都由客户端决定,改一个 accept 就能绕过。

拖拽上传

将文件拖到此处,或 点击选择拖拽文件到这里,或点击选择
vue
<SrUpload v-model="files" drag multiple action="/api/upload" />

拖拽区同时响应整片区域,而不是只有那个小图标可点—— 这符合用户对「拖到这里」的直觉。

尺寸与类型限制

将文件拖到此处,或 点击选择最多 3 个文件,单个不超过 10MB
vue
<SrUpload accept=".pdf,.docx" :max-size="10" :limit="3" multiple />

accept 用扩展名时注意:浏览器只做粗略匹配, 用户仍可通过「所有文件」选项选到别的类型。所以服务端校验不可省。

手动提交

auto-upload="false" 时,选中的文件不会立即上传, 而是先进入待上传列表,由宿主在合适时机调用 submit()

将文件拖到此处,或 点击选择选好文件后点下方按钮上传
vue
<script setup>
import { ref } from 'vue'
const uploadRef = ref()
const files = ref([])
</script>

<template>
  <SrUpload ref="uploadRef" v-model="files" :auto-upload="false" multiple />
  <SrButton variant="primary" @click="uploadRef.submit()">开始上传</SrButton>
</template>

何时该用手动提交

表单页里混着「文件」与「其他字段」时,通常是手动提交更合适—— 用户还没填完表单,文件就已经传到服务器上了,会产生一堆孤儿文件。

自定义上传

http-request 接管上传过程,用于需要签名、分片、或走 WebSocket 的场景。

将文件拖到此处,或 点击选择走自定义上传逻辑
vue
<script setup>
function myRequest({ file, onProgress, onSuccess, onError }) {
  // 自行处理上传,并在适当时机回调:
  // 模拟进度
  onProgress(50)
  setTimeout(() => onSuccess({ url: 'https://example.com/file.png' }), 600)
}
</script>

<template>
  <SrUpload :http-request="myRequest" />
</template>

必须调用 onSuccessonError,否则该文件会永远停在「上传中」—— 组件无从知道外部逻辑是成功还是失败。

上传前拦截

before-upload 返回 false 会取消这次上传;返回一个 File替换待上传的文件(压缩图片、改名等场景)。

将文件拖到此处,或 点击选择
vue
<script setup>
function checkFile(file) {
  if (file.name.includes('测试')) {
    return false   // 取消
  }
  return true
}
</script>

<template>
  <SrUpload :before-upload="checkFile" />
</template>

事件

将文件拖到此处,或 点击选择

最近结果:(尚未触发)

事件参数说明
update:modelValueSrUploadFile[]文件列表变化
success(file)单个文件上传成功
error(file, message)上传失败,第二个参数是错误信息
remove(file)移除文件
exceed(reason, file)超出限制,reason'limit' / 'size' / 'type' / 'accept'

error 是两个参数

失败信息同时存在于 file.message 和第二个参数里。

两个都给是有原因的:file 对象在列表渲染时更好用(能直接拿到文件名), 而 message 单独传参在只关心错误文案时更省事。

如果你从旧版本升级,注意第二个参数此前是 undefined—— 现在能正确拿到了。

Props

名称类型默认值说明
modelValueSrUploadFile[][]文件列表
actionstring上传地址
headersRecord<string, string>请求头(如鉴权 token)
dataRecord<string, string>随文件一起提交的额外字段
fieldNamestring'file'文件字段名
acceptstring接受的文件类型(非安全措施
limitnumber最多几个文件
maxSizenumber单文件大小上限(MB)
multiplebooleanfalse是否支持多选
dragbooleanfalse是否启用拖拽上传
autoUploadbooleantrue选中后是否立即上传
disabledbooleanfalse是否禁用
showFileListbooleantrue是否显示文件列表
tipstring提示文本
beforeUpload(file) => boolean | File | Promise<...>上传前拦截,可返回新文件替换
httpRequest(options) => void自定义上传实现

实例方法

方法说明
submit()提交全部待上传文件(auto-upload="false" 时使用)
clearFiles()清空文件列表

无障碍

  • 触发区是 <button> 语义,可键盘聚焦与触发
  • 拖拽是增强而非唯一途径——键盘用户与移动端用户都能通过点击完成上传
  • 上传失败的原因以文本呈现(而非仅用红色图标), 读屏软件能播报出具体哪里不合格

自用组件库 · 源码分发 · 不发布 npm