Skip to content

useFileUpload

文件上传管理Hook,提供文件列表管理、上传状态跟踪和预览功能。

前置依赖

依赖参数

参数名类型说明
env.vue.ref<T>(value: T) => Ref<T>Vue的ref函数
env.vue.shallowRef<T>(value: T) => Ref<T>Vue的shallowRef函数
env.vue.onUnmounted(fn: () => void) => void组件卸载钩子
env.host.createObjectURLWindow['URL']['createObjectURL']创建对象URL
env.host.revokeObjectURLWindow['URL']['revokeObjectURL']撤销对象URL

环境要求

  • Vue 3: Composition API
  • 浏览器: 支持File API和URL.createObjectURL

函数签名

typescript
function useFileUpload(
  initialFileList: FileUploadItem[],
  asyncBeforeUpload: (file: File) => Promise<boolean> | boolean,
  asyncUpload: (file: File) => Promise<string>,
  asyncAfterUpload: (file: File, url: string) => Promise<void> | void,
  env: UseFileUploadEnvironment
): UseFileUploadReturn

interface FileUploadItem {
  uid: string
  originFile: File
  status: 'ready' | 'uploading' | 'success' | 'failed'
  localPreview?: string
  onlinePreview?: string
}

interface UseFileUploadReturn {
  fileList: Ref<FileUploadItem[]>
  clear: () => void
  append: (files: File | File[]) => void
  replaceAt: (index: number, file: File) => void
}

参数

参数名类型必填说明
initialFileListFileUploadItem[]初始文件列表
asyncBeforeUpload(file: File) => Promise<boolean> | boolean上传前的异步处理函数,返回false可阻止上传
asyncUpload(file: File) => Promise<string>文件上传的异步函数,返回上传后的URL
asyncAfterUpload(file: File, url: string) => Promise<void> | void上传完成后的异步处理函数
envUseFileUploadEnvironment环境依赖对象

返回值

类型说明
fileListRef<FileUploadItem[]>
clear() => void
append(files: File | File[]) => void
replaceAt(index: number, file: File) => void

工作原理

  1. 初始化

    • 创建响应式的文件列表
    • 为每个文件生成唯一UID
    • 自动创建本地预览URL(通过URL.createObjectURL)
  2. 文件上传流程

    • 调用asyncBeforeUpload进行上传前验证
    • 如果返回false,文件状态设为failed
    • 如果通过验证,状态设为uploading
    • 调用asyncUpload执行实际上传
    • 上传成功后,状态设为success,保存onlinePreview
    • 调用asyncAfterUpload进行后续处理
    • 如果上传失败,状态设为failed
  3. 文件管理

    • append: 添加新文件并自动开始上传
    • replaceAt: 替换指定位置的文件,撤销旧文件预览URL
    • clear: 清空列表并撤销所有预览URL
  4. 资源清理

    • 组件卸载时自动撤销所有本地预览URL
    • 替换或删除文件时自动清理对应的预览URL

使用示例

typescript
import { ref, shallowRef, onUnmounted } from 'vue'
import { useFileUpload } from 'zcw-shared/vue-hooks/browser/useFileUpload'

const { fileList, append, clear, replaceAt } = useFileUpload(
  [],
  async (file) => {
    // 上传前验证
    if (file.size > 10 * 1024 * 1024) {
      return false // 阻止上传大于10MB的文件
    }
    return true
  },
  async (file) => {
    // 执行上传
    const formData = new FormData()
    formData.append('file', file)
    const response = await fetch('/api/upload', {
      method: 'POST',
      body: formData
    })
    const data = await response.json()
    return data.url
  },
  async (file, url) => {
    // 上传后处理
    console.log('上传成功', file.name, url)
  },
  {
    vue: { ref, shallowRef, onUnmounted },
    host: {
      createObjectURL: URL.createObjectURL,
      revokeObjectURL: URL.revokeObjectURL
    }
  }
)

// 添加单个文件
const fileInput = document.querySelector('input[type="file"]')
fileInput.addEventListener('change', (e) => {
  const files = (e.target as HTMLInputElement).files
  if (files && files.length > 0) {
    append(files[0])
  }
})

// 批量添加文件
append([file1, file2, file3])

// 替换文件
replaceAt(0, newFile)

// 清空列表
clear()