Files
soul-yongping/开发文档/8、部署/小程序头像上传优化说明.md

7.2 KiB
Raw Blame History

小程序头像上传优化说明

🔧 问题描述

旧逻辑

  • 小程序换头像时直接保存微信临时图片路径
  • 临时路径会过期,导致头像无法显示
  • 数据库存储的是微信的临时URL

问题

  • 微信临时图片有效期有限(通常几天后失效)
  • 头像无法长期显示
  • 用户体验差

解决方案

新逻辑

  1. 用户选择头像后,先上传图片到自己的服务器
  2. 服务器保存图片到 public/assets/avatars/ 目录
  3. 返回永久可访问的URL
  4. 将永久URL保存到数据库

优势

  • 图片永久保存在自己服务器
  • 头像不会失效
  • 完全可控

🔧 修改的文件

1. miniprogram/pages/my/my.js

修改函数: onChooseAvatar()

旧逻辑

// 直接使用临时路径
const avatarUrl = e.detail.avatarUrl
userInfo.avatar = avatarUrl

// 保存临时路径到数据库
await app.request('/api/user/update', {
  data: { userId: userInfo.id, avatar: avatarUrl }
})

新逻辑

// 1. 上传到服务器
const uploadRes = await wx.uploadFile({
  url: app.globalData.baseUrl + '/api/upload',
  filePath: tempAvatarUrl,
  name: 'file',
  formData: { folder: 'avatars' }
})

// 2. 获取永久URL
const avatarUrl = app.globalData.baseUrl + uploadRes.data.url

// 3. 保存永久URL到数据库
await app.request('/api/user/update', {
  data: { userId: userInfo.id, avatar: avatarUrl }
})

2. miniprogram/pages/settings/settings.js

修改函数: getWechatAvatar()

功能: 使用 wx.getUserProfile 获取微信头像

修改内容: 与 my.js 相同先上传图片再保存URL


📁 服务器存储路径

图片保存位置

public/assets/avatars/
  ├── 1738756123456_abc123.jpg
  ├── 1738756234567_def456.png
  └── ...

访问URL格式

https://soul.quwanzhi.com/assets/avatars/1738756123456_abc123.jpg

数据库存储

// users 表
{
  id: "user_123",
  avatar: "https://soul.quwanzhi.com/assets/avatars/1738756123456_abc123.jpg"
}

🔄 上传流程

完整流程图

用户点击更换头像
    ↓
微信弹出头像选择器chooseAvatar / getUserProfile
    ↓
获取临时图片路径tempAvatarUrl
    ↓
调用 wx.uploadFile 上传到服务器
    ↓
服务器保存图片到 public/assets/avatars/
    ↓
服务器返回永久URL
    ↓
更新本地 userInfoapp.globalData / storage
    ↓
调用 /api/user/update 保存到数据库
    ↓
完成!

代码实现

// 1. 获取临时头像
const tempAvatarUrl = e.detail.avatarUrl

// 2. 上传到服务器
const uploadRes = await new Promise((resolve, reject) => {
  wx.uploadFile({
    url: app.globalData.baseUrl + '/api/upload',
    filePath: tempAvatarUrl,
    name: 'file',
    formData: {
      folder: 'avatars'  // 保存到 avatars 文件夹
    },
    success: (res) => {
      const data = JSON.parse(res.data)
      if (data.success) {
        resolve(data)  // { success: true, data: { url: '/assets/avatars/xxx.jpg' } }
      } else {
        reject(new Error(data.error))
      }
    },
    fail: reject
  })
})

// 3. 拼接完整URL
const avatarUrl = app.globalData.baseUrl + uploadRes.data.url
// 结果: https://soul.quwanzhi.com/assets/avatars/xxx.jpg

// 4. 保存到数据库
await app.request('/api/user/update', {
  method: 'POST',
  data: { userId: userInfo.id, avatar: avatarUrl }
})

🔍 错误处理

1. 上传失败

try {
  // ... 上传逻辑
} catch (e) {
  wx.showToast({ 
    title: e.message || '上传失败,请重试', 
    icon: 'none' 
  })
}

2. 网络错误

  • 自动重试机制(可选)
  • 清晰的错误提示

3. 文件格式错误

  • 服务器会验证文件类型
  • 只允许 JPG、PNG、GIF、WebP、SVG
  • 文件大小限制 5MB

📊 服务器API

/api/upload - 图片上传接口

请求方式: POST (multipart/form-data)

参数:

  • file: 图片文件
  • folder: 保存文件夹(如 'avatars'

返回:

{
  "success": true,
  "data": {
    "url": "/assets/avatars/1738756123456_abc123.jpg",
    "fileName": "1738756123456_abc123.jpg",
    "size": 45678,
    "type": "image/jpeg"
  }
}

文件命名规则:

const timestamp = Date.now()
const randomStr = Math.random().toString(36).substring(2, 8)
const fileName = `${timestamp}_${randomStr}.${ext}`
// 例如: 1738756123456_abc123.jpg

测试清单

功能测试

  • 在"我的"页面点击头像,选择图片后成功上传
  • 上传后头像立即显示
  • 刷新页面后头像依然正常显示
  • 在设置页面使用"获取微信头像"功能正常
  • 后台管理页面能正确显示用户头像

数据验证

  • 数据库 users.avatar 字段保存的是完整URL
  • URL格式: https://soul.quwanzhi.com/assets/avatars/xxx.jpg
  • 不是微信临时路径(不包含 weixintmp

文件验证

  • 服务器 public/assets/avatars/ 目录存在
  • 上传的图片文件正常保存
  • 文件可通过浏览器直接访问

🚀 部署步骤

1. 确保目录存在

# 在服务器上创建目录
mkdir -p /www/wwwroot/soul.quwanzhi.com/public/assets/avatars
chmod 755 /www/wwwroot/soul.quwanzhi.com/public/assets/avatars

2. 部署代码

# 本地构建
pnpm build

# 部署到服务器
python devlop.py

# 重启PM2
pm2 restart soul

3. 小程序代码上传

  • 在微信开发者工具中上传代码
  • 提交审核
  • 发布新版本

📝 注意事项

1. 兼容性

  • 旧版本用户的头像可能还是微信临时路径
  • 建议提示用户重新上传头像

2. 存储空间

  • 每个头像约 50-200KB
  • 10000个用户约 0.5-2GB
  • 定期清理无用头像(可选)

3. CDN优化可选

  • 如果用户量大考虑使用CDN加速
  • public/assets/avatars/ 目录同步到CDN

4. 图片压缩(可选)

  • 可以在上传时自动压缩图片
  • 减少存储空间和加载时间

🔄 数据迁移(可选)

如果需要迁移旧数据(微信临时路径 → 永久URL

方案1: 提示用户重新上传

// 在小程序中检查头像URL
if (userInfo.avatar && userInfo.avatar.includes('weixin')) {
  // 提示用户重新上传头像
  wx.showModal({
    title: '头像过期',
    content: '请重新上传您的头像',
    confirmText: '立即上传'
  })
}

方案2: 自动下载并上传(服务器端)

// 在服务器端批量处理
// 1. 查询所有微信临时路径的头像
// 2. 下载图片
// 3. 上传到自己服务器
// 4. 更新数据库
// (需要开发专门的迁移脚本)

完成状态

  • 修改 my.jsonChooseAvatar() 函数
  • 修改 settings.jsgetWechatAvatar() 函数
  • 使用现有的 /api/upload 接口
  • 添加错误处理和日志
  • 创建说明文档

📚 相关文档

  • 后台订单显示优化说明.md - 后台显示头像相关
  • /api/upload 接口文档

优化完成!小程序头像将永久保存在自己的服务器上,不会再失效!