Skip to content

阿里云OSS管理功能在Vue客户端的实现方案文档

1. 接口地址概述

以下是所有阿里云OSS管理相关接口的基础路径和功能分组:

接口名称方法接口路径功能描述
创建文件夹POST/api/aliyun-oss/create-folder在指定路径下创建新文件夹
上传文件POST/api/aliyun-oss/upload-file上传文件到指定OSS路径
删除文件DELETE/api/aliyun-oss/delete-file删除指定的OSS文件或文件夹
列出文件GET/api/aliyun-oss/list-files列出指定路径下的文件和文件夹
批量删除文件POST/api/aliyun-oss/batch-delete批量删除多个OSS文件或文件夹

2. 主要功能实现

2.1 创建文件夹功能

业务逻辑说明

  • 用户在当前目录下输入文件夹名称,系统向服务器发送创建文件夹请求
  • 服务器验证权限和文件夹名称合法性,成功后在OSS上创建文件夹
  • 客户端收到成功响应后,刷新当前目录文件列表

Vue代码实现

javascript
// 创建目录
async handleCreateDir() {
  try {
    this.$refs.dirForm.validate(async (valid) => {
      if (valid) {
        const dirKey = this.currentPath + this.dirForm.dirName + '/'
        await createOSSDirectory({
          bucket: 'aigc-sz-linkt',
          key: dirKey
        })
        ElMessage.success('文件夹创建成功')
        this.createDirDialogVisible = false
        this.loadFiles()
      }
    })
  } catch (error) {
    ElMessage.error('创建文件夹失败: ' + error.message)
    console.error('创建文件夹失败:', error)
  }
}

2.2 上传文件功能

业务逻辑说明

  • 用户选择一个或多个文件,系统显示文件列表并等待确认
  • 用户点击上传后,系统依次上传每个文件,显示整体上传进度
  • 上传完成后刷新文件列表并提示成功信息

Vue代码实现

javascript
// 开始上传
async startUpload() {
  try {
    this.uploadProgress = 0
    
    for (let i = 0; i < this.uploadFileList.length; i++) {
      const file = this.uploadFileList[i].raw
      this.currentUploadFileName = file.name
      
      const result = await uploadToAliOSS(file, {
        businessType: 'aigc',
        onProgress: (progressEvent) => {
          if (progressEvent.total) {
            const fileProgress = Math.round((progressEvent.loaded / progressEvent.total) * 100)
            // 计算整体进度
            this.uploadProgress = Math.round(((i + (fileProgress / 100)) / this.uploadFileList.length) * 100)
          }
        }
      })
      
      console.log('文件上传成功:', result)
    }
    
    ElMessage.success('所有文件上传成功')
    this.uploadDialogVisible = false
    this.loadFiles()
  } catch (error) {
    ElMessage.error('文件上传失败: ' + error.message)
    console.error('文件上传失败:', error)
  }
}

2.3 删除文件功能

业务逻辑说明

  • 用户选择单个文件或文件夹,点击删除按钮
  • 系统弹出确认对话框,用户确认后发送删除请求
  • 服务器执行删除操作,客户端刷新文件列表

Vue代码实现

javascript
// 删除文件
async confirmDelete() {
  try {
    if (this.fileToDelete) {
      // 单个删除
      await deleteOSSFile({
        bucket: 'aigc-sz-linkt',
        key: this.fileToDelete.key
      })
      ElMessage.success('删除成功')
    } else if (this.selectedFiles.length > 0) {
      // 批量删除
      const keys = this.selectedFiles.map(file => file.key)
      await batchDeleteOSSFiles({
        bucket: 'aigc-sz-linkt',
        keys: keys
      })
      ElMessage.success(`成功删除 ${keys.length} 个文件/目录`)
    }
    
    this.deleteConfirmVisible = false
    this.loadFiles()
  } catch (error) {
    ElMessage.error('删除失败: ' + error.message)
    console.error('删除失败:', error)
  }
}

2.4 列出文件功能

业务逻辑说明

  • 用户进入页面或切换目录时,系统发送列出文件请求
  • 请求包含当前路径、分隔符和最大返回数量等参数
  • 服务器返回文件和文件夹列表,客户端进行处理并展示

Vue代码实现

javascript
// 加载文件列表
async loadFiles() {
  try {
    this.loading = true
    const result = await listOSSFiles({
      bucket: 'aigc-sz-linkt',
      prefix: this.currentPath,
      delimiter: '/',
      maxKeys: 1000
    })
    
    // 处理返回的文件数据
    this.files = this.processFileData(result)
  } catch (error) {
    ElMessage.error('加载文件列表失败: ' + error.message)
    console.error('加载文件列表失败:', error)
  } finally {
    this.loading = false
    this.selectedFiles = []
  }
}

// 处理文件数据
processFileData(data) {
  const files = []
  
  // 处理目录
  if (data.commonPrefixes && data.commonPrefixes.length > 0) {
    data.commonPrefixes.forEach(prefix => {
      const dirName = prefix.substring(this.currentPath.length).replace(/\/$/, '')
      files.push({
        name: dirName,
        key: prefix,
        isDir: true,
        type: 'directory',
        lastModified: ''
      })
    })
  }
  
  // 处理文件
  if (data.contents && data.contents.length > 0) {
    data.contents.forEach(content => {
      // 跳过目录项
      if (content.key.endsWith('/')) return
      
      const fileName = content.key.substring(this.currentPath.length)
      files.push({
        name: fileName,
        key: content.key,
        isDir: false,
        type: 'file',
        size: content.size || 0,
        lastModified: content.lastModified ? new Date(content.lastModified).toLocaleString() : ''
      })
    })
  }
  
  return files
}

2.5 批量删除文件功能

业务逻辑说明

  • 用户选择多个文件或文件夹,点击批量删除按钮
  • 系统提示删除确认信息,包含选中的项目数量
  • 用户确认后,系统将所有选中项的key发送到服务器进行批量删除

Vue代码实现

javascript
// 批量删除
batchDelete() {
  this.fileToDelete = null
  this.deleteConfirmMessage = `确定要删除选中的 ${this.selectedFiles.length} 个文件/目录吗?`
  this.deleteConfirmVisible = true
}

// 在confirmDelete方法中的批量删除逻辑
if (this.selectedFiles.length > 0) {
  // 批量删除
  const keys = this.selectedFiles.map(file => file.key)
  await batchDeleteOSSFiles({
    bucket: 'aigc-sz-linkt',
    keys: keys
  })
  ElMessage.success(`成功删除 ${keys.length} 个文件/目录`)
}

3. 错误处理与状态管理

3.1 统一的axios响应处理

业务逻辑说明

  • 所有API请求都应通过封装好的axios实例发送
  • 统一处理请求成功、失败、超时等情况
  • 针对不同类型的错误提供用户友好的提示信息

错误处理实现建议

javascript
// API请求统一封装示例
async function requestAPI(config) {
  try {
    const response = await axios(config)
    
    if (response.data.code === 200) {
      return response.data.data
    } else {
      ElMessage.error(response.data.message || '操作失败')
      throw new Error(response.data.message || '操作失败')
    }
  } catch (error) {
    // 网络错误处理
    if (error.response) {
      // 服务器返回了错误状态码
      switch (error.response.status) {
        case 401:
          ElMessage.error('未授权,请重新登录')
          router.push('/login')
          break
        case 403:
          ElMessage.error('权限不足,无法执行此操作')
          break
        case 404:
          ElMessage.error('请求的资源不存在')
          break
        case 500:
          ElMessage.error('服务器内部错误,请稍后再试')
          break
        default:
          ElMessage.error(error.response.data.message || '操作失败')
      }
    } else if (error.request) {
      // 请求已发送但没有收到响应
      ElMessage.error('网络连接失败,请检查网络设置')
    } else {
      // 请求配置出错
      ElMessage.error('请求配置错误: ' + error.message)
    }
    throw error
  }
}

3.2 状态管理

业务逻辑说明

  • 使用Vue的data属性管理组件内部状态
  • 包括加载状态、文件列表数据、当前路径、选中文件等
  • 适当使用computed属性处理派生数据

状态管理实现

javascript
data() {
  return {
    loading: false, // 加载状态
    files: [], // 文件列表数据
    searchKeyword: '', // 搜索关键词
    selectedFiles: [], // 选中的文件列表
    currentPath: '', // 当前路径
    currentPathArray: [''], // 当前路径的数组表示
    createDirDialogVisible: false, // 创建文件夹对话框可见状态
    dirForm: { // 文件夹表单数据
      dirName: ''
    },
    dirRules: { // 文件夹表单验证规则
      dirName: [
        { required: true, message: '请输入文件夹名称', trigger: 'blur' },
        { pattern: /^[^\\/:*?"<>|]+$/, message: '文件夹名称不能包含特殊字符', trigger: 'blur' }
      ]
    },
    uploadDialogVisible: false, // 上传对话框可见状态
    uploadFileList: [], // 待上传文件列表
    uploadProgress: 0, // 上传进度
    currentUploadFileName: '', // 当前上传文件名
    deleteConfirmVisible: false, // 删除确认对话框可见状态
    deleteConfirmMessage: '', // 删除确认信息
    fileToDelete: null // 待删除的单个文件
  }
},
computed: {
  // 根据搜索关键词过滤文件列表
  filteredFiles() {
    if (!this.searchKeyword) {
      return this.files
    }
    return this.files.filter(file => 
      file.name.toLowerCase().includes(this.searchKeyword.toLowerCase())
    )
  }
}

4. 页面组件设计建议

4.1 文件浏览器组件

业务逻辑说明

  • 主要展示文件和文件夹列表,支持导航、搜索和选择
  • 使用Element UI的Table组件实现表格展示
  • 支持文件类型图标、大小格式化和修改时间显示

组件实现

html
<!-- 文件列表 -->
<div class="file-list">
  <el-table
    v-loading="loading"
    :data="filteredFiles"
    @selection-change=