2025.3.3

这段代码是前端实现文件上传的核心模块,主要包含请求配置、身份验证、错误处理等功能。以下是详细解析:


代码结构解析

1. 模块导入

import store from '@/store'        // 状态管理(Vuex)
import config from '@/config'       // 项目配置
import { getToken } from '@/utils/auth' // 认证相关工具
import errorCode from '@/utils/errorCode' // 错误码映射
import { toast, showConfirm, tansParams } from '@/utils/common' // 通用工具
  • 核心依赖:集成了状态管理、项目配置和工具函数

2. 基础配置

let timeout = 10000 // 默认超时时间
const baseUrl = config.baseUrl // 从配置获取基础API地址
  • 超时控制:10秒无响应自动终止请求
  • 环境适配:通过config.baseUrl实现多环境切换

核心函数 upload

1. 身份验证处理

// 是否需要携带Token (默认携带)
const isToken = (config.headers || {}).isToken === false 
config.header = config.header || {}
if (getToken() && !isToken) {
    config.header['Authorization'] = 'Bearer ' + getToken()
}
  • 鉴权逻辑
    • 默认携带Token
    • 可通过headers: { isToken: false }禁用
  • Token格式:Bearer Token标准方案

2. GET参数处理

if (config.params) {
    let url = config.url + '?' + tansParams(config.params)
    url = url.slice(0, -1) // 去除末尾多余的&
    config.url = url
}
  • URL参数序列化:使用tansParams转换对象为查询字符串
  • 适用场景:需要GET参数的文件下载接口

3. 上传请求封装

return new Promise((resolve, reject) => {
    uni.uploadFile({
        timeout: config.timeout || timeout, // 超时配置
        url: baseUrl + config.url,         // 完整请求地址
        filePath: config.filePath,         // 待上传文件路径
        name: config.name || 'file',       // 上传字段名(默认file)
        header: config.header,             // 自定义请求头
        formData: config.formData,         // 附加表单数据
        // 成功回调
        success: (res) => {
            // 响应处理逻辑...
        },
        // 失败回调
        fail: (error) => {
            // 错误处理逻辑...
        }
    })
})

响应处理逻辑

成功回调处理流程

let result = JSON.parse(res.data) // 解析响应数据
const code = result.code || 200    // 获取状态码
const msg = errorCode[code] || result.msg || errorCode['default'] // 获取错误信息

// 状态码分支处理
if (code === 200) {
    resolve(result) // 成功处理
} else if (code == 401) { // 未授权
    showConfirm("登录过期提示").then(res => {
        if (res.confirm) {
            store.dispatch('LogOut').then(() => { // 执行登出
                uni.reLaunch({ url: '/login' }) // 跳转登录页
            })
        }
    })
    reject('会话过期提示')
} else if (code === 500) { // 服务器错误
    toast(msg)
    reject('500')
} else if (code !== 200) { // 其他错误
    toast(msg)
    reject(code)
}

失败回调处理

let { message } = error
// 错误类型判断
if (message == 'Network Error') {
    message = '后端接口连接异常'
} else if (message.includes('timeout')) {
    message = '系统接口请求超时'
} else if (message.includes('Request failed with status code')) {
    message = '系统接口' + message.substr(-3) + '异常'
}
toast(message) // 显示错误提示
reject(error)  // 传递错误对象

代码亮点分析

  1. 安全设计

    • 自动携带Token机制
    • 401自动登出保护
  2. 健壮性设计

    • 多层错误码映射 (errorCode)
    • 网络异常分类处理
  3. 用户体验优化

    • 统一错误提示 (toast)
    • 会话过期二次确认弹窗
  4. 可维护性

    • 配置参数分离 (config.js)
    • 状态码集中管理

潜在改进建议

  1. 文件校验增强
// 上传前校验文件类型和大小
const MAX_SIZE = 10 * 1024 * 1024 // 10MB
if (config.file.size > MAX_SIZE) {
    return reject('文件大小超过限制')
}
  1. 进度反馈
// 添加进度回调
uni.uploadFile({
    // ...
    progress: (res) => {
        console.log('上传进度:', res.progress)
    }
})
  1. 重试机制
let retryCount = 0
const retry = () => {
    if(retryCount < 3){
        retryCount++
        upload(config)
    }
}
  1. 文件分片上传
// 大文件分片处理
const chunkSize = 2 * 1024 * 1024 // 2MB分片
for(let i=0; i<Math.ceil(file.size/chunkSize); i++){
    const chunk = file.slice(i*chunkSize, (i+1)*chunkSize)
    uploadChunk(chunk, i)
}

典型使用场景

// 在Vue组件中的使用
import upload from '@/utils/upload'

export default {
    methods: {
        async handleUpload(file) {
            try {
                const res = await upload({
                    url: '/api/upload',
                    filePath: file.path,
                    name: 'avatar',
                    formData: {
                        userId: '123'
                    }
                })
                console.log('上传结果:', res)
            } catch (error) {
                console.error('上传失败:', error)
            }
        }
    }
}

通过这个高度封装的upload模块,开发者可以快速实现安全可靠的文件上传功能,同时保持业务代码的简洁性。

posted @ 2025-03-03 23:01  258333  阅读(13)  评论(0)    收藏  举报