Files
digital-pilates/docs/cos.md
richarjiang 321947db98 feat: 更新应用版本和集成腾讯云 COS 上传功能
- 将应用版本更新至 1.0.2,修改相关配置文件
- 集成腾讯云 COS 上传功能,新增相关服务和钩子
- 更新 AI 体态评估页面,支持照片上传和评估结果展示
- 添加雷达图组件以展示评估结果
- 更新样式以适应新功能的展示和交互
- 修改登录页面背景效果,提升用户体验
2025-08-13 15:21:54 +08:00

5.6 KiB
Raw Blame History

腾讯云 COS 上传集成说明

本文档记录本项目在前端Expo/React Native侧对腾讯云 COS 的接入方式与使用规范,包含配置、接口约定、上传用法、进度/取消/重试、URL 构建、权限与安全、常见问题等。

概览

  • 依赖:cos-js-sdk-v5
  • 临时密钥接口:GET /api/users/cos-token
  • 统一封装:
    • 配置:constants/Cos.ts
    • 上传服务:services/cos.ts
    • Hookhooks/useCosUpload.ts

安装与依赖

已在 package.json 中添加:

{
  "dependencies": {
    "cos-js-sdk-v5": "^1.6.0"
  }
}

配置

编辑 constants/Cos.ts,填入实际 COS 参数:

export const COS_BUCKET = 'your-bucket-125xxxxxxx';
export const COS_REGION = 'ap-shanghai';
export const COS_PUBLIC_BASE = 'https://your-bucket-125xxxxxxx.cos.ap-shanghai.myqcloud.com';
export const COS_KEY_PREFIX = 'uploads/';

说明:

  • COS_PUBLIC_BASE若桶或 CDN 具有公网访问,使用对应域名(建议 HTTPS。若为私有桶可忽略该项前端不能直接拼公开 URL
  • buildCosKey 会依据日期和随机串生成不重复 Key可通过 prefix/userId 定制目录。

后端接口约定:/api/users/cos-token

  • 方法:GET
  • 鉴权:建议要求登录态,后端根据用户权限签发最小权限临时凭证。
  • 响应体示例(关键字段):
{
  "credentials": {
    "tmpSecretId": "TMPID...",
    "tmpSecretKey": "TMPKEY...",
    "sessionToken": "SESSION_TOKEN..."
  },
  "startTime": 1730000000,
  "expiredTime": 1730001800
}
  • 最小权限策略建议(示例,后端侧):
{
  "version": "2.0",
  "statement": [
    {
      "action": [
        "name/cos:PutObject",
        "name/cos:InitiateMultipartUpload",
        "name/cos:UploadPart",
        "name/cos:CompleteMultipartUpload"
      ],
      "effect": "allow",
      "resource": [
        "qcs::cos:ap-shanghai:uid/125xxxxxxx:your-bucket-125xxxxxxx/*"
      ]
    }
  ]
}

注意:对上传路径进行前缀限制(如 uploads/*)能进一步收敛权限范围。

前端用法一Hook推荐

在页面/组件内使用 useCosUpload,支持进度、取消与重试。

import { useCosUpload } from '@/hooks/useCosUpload';
import * as ImagePicker from 'expo-image-picker';

export default function Uploader() {
  const { upload, progress, uploading, cancel } = useCosUpload({ prefix: 'images/', userId: 'uid-123' });

  const pickAndUpload = async () => {
    const res = await ImagePicker.launchImageLibraryAsync({ mediaTypes: ImagePicker.MediaTypeOptions.Images });
    if (res.canceled || !res.assets?.[0]) return;
    const asset = res.assets[0];
    const result = await upload({ uri: asset.uri, name: asset.fileName, type: asset.mimeType });
    console.log('uploaded:', result); // { key, url }
  };

  return null;
}

说明:

  • progress 范围 0-1uploading 指示进行中;可随时 cancel()
  • 未开启公网访问时,url 可能为空(需服务端签名下载)。

前端用法二:直接调用服务

services/cos.ts 提供基础方法:

import { uploadWithRetry } from '@/services/cos';

const { key, etag } = await uploadWithRetry({
  key: 'uploads/demo.png',
  body: blob,
  contentType: 'image/png'
});
  • 进度回调:onProgress: ({ percent }) => { ... }
  • 取消:传入 signal: AbortSignal
  • 重试:maxRetries/backoffMs 配置指数退避

URL 构建

若为公网可访问场景,使用:

import { buildPublicUrl } from '@/constants/Cos';
const url = buildPublicUrl(key);

若为私有桶,请改走服务端生成临时下载链接或代理下载。

大文件与分片上传

当前默认使用 putObject。若需大文件/断点续传,建议切换 SDK 的分片接口 sliceUploadFile

const taskId = cos.sliceUploadFile({
  Bucket: COS_BUCKET,
  Region: COS_REGION,
  Key: key,
  Body: fileOrBlob,
  onProgress(progress) { /* ... */ }
}, (err, data) => { /* ... */ });

如需切换,可在 services/cos.ts 中将 putObject 替换为 sliceUploadFile,并保留同样的进度、取消与重试包装。

CORS 与浏览器(如使用 Web

  • COS 控制台需配置 CORS允许来源域名、方法PUT/POST/OPTIONS、请求头Authorizationx-cos-* 等)、暴露头。
  • 若通过自有域名/网关代理,也需在代理层正确透传 CORS 与签名头。

安全与最佳实践

  • 永久密钥仅存在服务端,通过 /api/users/cos-token 颁发短期凭证。
  • 严控临时凭证权限与有效期,并限制上传前缀。
  • 前端仅持有短期凭证;错误重试次数受限,避免暴力重放。

常见问题排查

  • 403/签名失败:确认服务端时间同步、region/bucket/resource 配置正确;临时密钥未过期。
  • CORS 失败:检查 COS 跨域规则;确认需要的请求头(含 Authorization)均已放行。
  • URL 访问 403私有桶下请改用服务端签名下载或为指定前缀开启公共读谨慎
  • MIME/ContentType从 ImagePicker 取 mimeType,或按扩展名兜底设置。

测试清单

  • 小图上传成功且进度递增、可取消。
  • 取消后不再继续发片段;重试如期生效。
  • 返回的 key 能通过 buildPublicUrl 拼出可访问地址(公网桶)。
  • 临时密钥过期后,能够重新获取并继续上传。

变更点速记

  • 依赖:cos-js-sdk-v5
  • 新增:constants/Cos.tsservices/cos.tshooks/useCosUpload.ts
  • 接口:GET /api/users/cos-token(返回临时凭证)

如需我将某页面接入示例按钮或改造为分片上传,请在需求中指明目标文件与交互期望。