Skip to content

FileUpload 文件上传

文件上传组件,支持多文件上传、拖拽上传、进度显示等功能。

基础用法

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'

const fileList = ref<string[]>([])
</script>

<template>
  <FileUpload v-model="fileList" />
</template>

多文件上传

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'

const fileList = ref<string[]>([])
</script>

<template>
  <FileUpload 
    v-model="fileList" 
    :limit="10"
    multiple 
  />
</template>

拖拽上传

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'

const fileList = ref<string[]>([])
</script>

<template>
  <FileUpload 
    v-model="fileList"
    drag
  >
    <template #default>
      <div class="upload-drag-area">
        <p class="upload-drag-icon">📁</p>
        <p class="upload-drag-text">将文件拖到此处,或点击上传</p>
      </div>
    </template>
  </FileUpload>
</template>

<style scoped>
.upload-drag-area {
  padding: 40px;
  text-align: center;
}

.upload-drag-icon {
  font-size: 48px;
  margin-bottom: 16px;
}

.upload-drag-text {
  color: #999;
}
</style>

限制文件类型

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'

const fileList = ref<string[]>([])
</script>

<template>
  <FileUpload 
    v-model="fileList"
    :accept="['.pdf', '.doc', '.docx', '.xls', '.xlsx']"
  />
</template>

限制文件大小

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'

const fileList = ref<string[]>([])
</script>

<template>
  <FileUpload 
    v-model="fileList"
    :max-size="10"
    :on-exceed-size="handleExceedSize"
  />
</template>

<script setup lang="ts">
const handleExceedSize = (file: File) => {
  message.error(`文件 ${file.name} 超过 10MB`)
}
</script>

API

Props

参数说明类型默认值
modelValue绑定值string | string[]-
multiple是否支持多选booleanfalse
limit最大上传数量numberInfinity
maxSize文件大小限制(MB)number100
accept接受的文件类型string[][]
action上传地址string/api/upload
headers上传请求头object{}
data上传额外参数object{}
drag是否启用拖拽上传booleanfalse
disabled是否禁用booleanfalse
showFileList是否显示文件列表booleantrue
autoUpload是否自动上传booleantrue

Events

事件名说明回调参数
update:modelValue值变化时触发(value: string | string[]) => void
change文件状态改变时触发(fileList: UploadFile[]) => void
success上传成功时触发(response: any, file: UploadFile) => void
error上传失败时触发(error: Error, file: UploadFile) => void
progress上传进度变化时触发(percent: number, file: UploadFile) => void
remove删除文件时触发(file: UploadFile) => void
exceed超过限制数量时触发(files: File[]) => void
exceedSize超过文件大小时触发(file: File) => void

Slots

插槽名说明参数
default自定义上传按钮-
tip自定义提示信息-
file自定义文件列表项{ file: UploadFile }

Methods

方法名说明参数
submit手动上传-
clearFiles清空文件列表-
abort取消上传(file?: UploadFile) => void

完整示例

vue
<script setup lang="ts">
import { ref } from 'vue'
import { message } from 'ant-design-vue'
import { FileUpload } from '@vben/common-ui'
import type { UploadFile } from 'ant-design-vue'

const fileList = ref<string[]>([])
const uploadRef = ref()

const handleSuccess = (response: any, file: UploadFile) => {
  message.success(`${file.name} 上传成功`)
}

const handleError = (error: Error, file: UploadFile) => {
  message.error(`${file.name} 上传失败:${error.message}`)
}

const handleProgress = (percent: number, file: UploadFile) => {
  console.log(`${file.name} 上传进度:${percent}%`)
}

const handleRemove = (file: UploadFile) => {
  console.log('删除文件:', file)
}

const handleExceed = (files: File[]) => {
  message.warning(`最多只能上传 5 个文件,当前选择了 ${files.length} 个文件`)
}

const handleExceedSize = (file: File) => {
  message.error(`文件 ${file.name} 超过 10MB`)
}

const handleSubmit = () => {
  uploadRef.value?.submit()
}

const handleClear = () => {
  uploadRef.value?.clearFiles()
}
</script>

<template>
  <div>
    <FileUpload
      ref="uploadRef"
      v-model="fileList"
      multiple
      drag
      :limit="5"
      :max-size="10"
      :accept="['.pdf', '.doc', '.docx', '.xls', '.xlsx', '.zip']"
      action="/api/upload/file"
      :headers="{ Authorization: 'Bearer token' }"
      :data="{ folder: 'documents' }"
      :auto-upload="false"
      @success="handleSuccess"
      @error="handleError"
      @progress="handleProgress"
      @remove="handleRemove"
      @exceed="handleExceed"
      @exceed-size="handleExceedSize"
    >
      <template #default>
        <div class="upload-drag-area">
          <p class="upload-drag-icon">📁</p>
          <p class="upload-drag-text">将文件拖到此处,或点击上传</p>
          <p class="upload-drag-hint">
            支持 PDF、Word、Excel、ZIP 格式,单个文件不超过 10MB
          </p>
        </div>
      </template>
      
      <template #tip>
        <div class="upload-tip">
          <p>支持扩展名:.pdf .doc .docx .xls .xlsx .zip</p>
          <p>单个文件大小不超过 10MB,最多上传 5 个文件</p>
        </div>
      </template>
    </FileUpload>
    
    <div class="upload-actions">
      <a-space>
        <a-button type="primary" @click="handleSubmit">开始上传</a-button>
        <a-button @click="handleClear">清空列表</a-button>
      </a-space>
    </div>
  </div>
</template>

<style scoped>
.upload-drag-area {
  padding: 60px 40px;
  text-align: center;
  background: #fafafa;
  border: 2px dashed #d9d9d9;
  border-radius: 8px;
  transition: all 0.3s;
}

.upload-drag-area:hover {
  border-color: #40a9ff;
  background: #f0f8ff;
}

.upload-drag-icon {
  font-size: 64px;
  margin-bottom: 16px;
}

.upload-drag-text {
  font-size: 16px;
  color: #333;
  margin-bottom: 8px;
}

.upload-drag-hint {
  font-size: 14px;
  color: #999;
}

.upload-tip {
  margin-top: 8px;
  color: #999;
  font-size: 12px;
}

.upload-tip p {
  margin: 4px 0;
}

.upload-actions {
  margin-top: 16px;
}
</style>

自定义上传

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'
import axios from 'axios'

const fileList = ref<string[]>([])

const customUpload = async (file: File) => {
  const formData = new FormData()
  formData.append('file', file)
  
  const { data } = await axios.post('/api/upload', formData, {
    headers: { 'Content-Type': 'multipart/form-data' },
    onUploadProgress: (progressEvent) => {
      const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total!)
      console.log(`上传进度:${percent}%`)
    }
  })
  
  return data.url
}
</script>

<template>
  <FileUpload 
    v-model="fileList"
    :custom-request="customUpload"
  />
</template>

文件预览

vue
<script setup lang="ts">
import { ref } from 'vue'
import { FileUpload } from '@vben/common-ui'

const fileList = ref<string[]>([])

const handlePreview = (file: UploadFile) => {
  // 根据文件类型进行预览
  const fileType = file.name.split('.').pop()?.toLowerCase()
  
  if (['jpg', 'jpeg', 'png', 'gif'].includes(fileType!)) {
    // 图片预览
    window.open(file.url)
  } else if (fileType === 'pdf') {
    // PDF 预览
    window.open(file.url)
  } else {
    // 下载文件
    const link = document.createElement('a')
    link.href = file.url!
    link.download = file.name
    link.click()
  }
}
</script>

<template>
  <FileUpload 
    v-model="fileList"
    @preview="handlePreview"
  />
</template>

注意事项

注意

  1. 上传的文件会自动转换为 URL 或返回服务器地址
  2. 多文件上传时,返回的是数组格式
  3. 建议设置合理的文件大小限制,避免上传过大的文件
  4. 拖拽上传需要浏览器支持 HTML5 Drag and Drop API

提示

  • 可以通过 accept 属性限制上传的文件类型
  • 使用 maxSize 属性限制文件大小
  • 设置 autoUpload={false} 可以手动控制上传时机
  • 使用 customRequest 可以完全自定义上传逻辑

相关链接

MIT License