uniapp 实现腾讯云 COS 存储全攻略(跨平台文件管理)

引言

腾讯云对象存储(COS)提供高可用、低成本的存储方案,本文将手把手教你如何在 uniapp 中实现 图片/视频/文件 的上传、下载、删除全流程,支持 App/H5/小程序 全端运行。

一、技术选型对比

方案 优点 缺点
直传 COS 简单快速 需暴露永久密钥
临时密钥签名 安全性高 需开发后端接口
客户端签名 无需后端 仅限简单场景

推荐方案:临时密钥签名(兼顾安全与便捷)

二、完整实现步骤

1. 准备工作

1.1 注册腾讯云账号
  • 访问 COS 控制台
  • 创建存储桶(Bucket),记录以下信息:
    • 地域:如 ap-guangzhou
    • 存储桶名称:如 example-1250000000
1.2 安装 COS SDK
npm install cos-js-sdk-v5 --save

2. 初始化 COS 客户端

// utils/cos.js
import COS from 'cos-js-sdk-v5';

// 获取临时密钥(需通过后端接口)
async function getTempCredentials() {
  // 实际开发中应通过云函数或自有服务获取
  return {
    TmpSecretId: 'AKIDxxxxxxxx',
    TmpSecretKey: 'xxxxxxxx',
    XCosSecurityToken: 'xxxxxxxx',
    ExpiredTime: 1720000000
  };
}

export async function createCOSClient() {
  const credentials = await getTempCredentials();
  
  return new COS({
    getAuthorization: function (options, callback) {
      callback({
        TmpSecretId: credentials.TmpSecretId,
        TmpSecretKey: credentials.TmpSecretKey,
        XCosSecurityToken: credentials.XCosSecurityToken,
        ExpiredTime: credentials.ExpiredTime
      });
    }
  });
}

3. 核心功能实现

3.1 文件上传(分片上传示例)
async function uploadFile(filePath) {
  const client = await createCOSClient();
  
  return new Promise((resolve, reject) => {
    client.sliceUploadFile({
      Bucket: 'example-1250000000',
      Region: 'ap-guangzhou',
      Key: `images/${Date.now()}_${filePath.name}`, // 文件路径规则
      Body: filePath,
      onProgress: function(info) {
        const percent = parseInt(info.percent * 100);
        uni.showLoading({ title: `上传中 ${percent}%` });
      }
    }, (err, data) => {
      uni.hideLoading();
      if (err) return reject(err);
      resolve(data.Location); // 返回文件访问URL
    });
  });
}

// 使用示例
uni.chooseImage({
  success: async (res) => {
    const filePath = res.tempFilePaths[0];
    try {
      const url = await uploadFile(filePath);
      console.log('上传成功:', url);
    } catch (err) {
      uni.showToast({ title: '上传失败', icon: 'none' });
    }
  }
});
3.2 文件下载
async function downloadFile(fileUrl) {
  const client = await createCOSClient();
  
  return new Promise((resolve, reject) => {
    client.getObjectUrl({
      Bucket: 'example-1250000000',
      Region: 'ap-guangzhou',
      Key: getKeyFromUrl(fileUrl), // 从URL解析文件Key
      Sign: true, // 生成带签名的临时URL
      Expires: 60 // 有效期60秒
    }, (err, data) => {
      if (err) return reject(err);
      
      // 跳转下载
      uni.downloadFile({
        url: data.Url,
        success: (res) => {
          if (res.statusCode === 200) {
            uni.saveFileToPhotosAlbum({
              filePath: res.tempFilePath
            });
          }
        }
      });
    });
  });
}
3.3 文件删除
async function deleteFile(fileKey) {
  const client = await createCOSClient();
  
  return new Promise((resolve, reject) => {
    client.deleteObject({
      Bucket: 'example-1250000000',
      Region: 'ap-guangzhou',
      Key: fileKey
    }, (err, data) => {
      if (err) return reject(err);
      resolve(data);
    });
  });
}

4. 跨平台适配处理

4.1 H5 端特殊配置
// 配置CORS规则(需在COS控制台设置)
{
  "AllowedOrigin": ["*"],
  "AllowedMethod": ["PUT", "GET", "POST", "DELETE"],
  "AllowedHeader": ["*"]
}
4.2 小程序端限制处理
// 小程序需使用chooseMessageFile代替chooseImage
uni.chooseMessageFile({
  count: 1,
  type: 'file',
  success: (res) => {
    // 处理文件上传
  }
});

三、性能优化技巧

1. 大文件上传优化

// 使用分片上传(默认已启用)
client.sliceUploadFile({
  // ...
  SliceSize: 1024 * 1024 * 5, // 每片5MB
  Threads: 3 // 并发线程数
});

2. 断点续传实现

// 记录上传进度到本地存储
uni.setStorageSync(`upload_${fileKey}`, progress);

// 初始化时检查续传状态
const savedProgress = uni.getStorageSync(`upload_${fileKey}`);
if (savedProgress) {
  // 恢复上传
}

3. 图片压缩处理

// 使用uni-app内置压缩
uni.compressImage({
  src: filePath,
  quality: 80,
  success: (res) => {
    uploadFile(res.tempFilePath);
  }
});

四、常见问题解决

Q1: 上传报错 “No Permission”

  • 检查存储桶权限策略
  • 确认临时密钥有效性
  • 验证文件路径是否包含特殊字符

Q2: 小程序无法选择文件

  • 添加文件类型白名单:
    {
      "pages": ["pages/index/index"],
      "permission": {
        "scope.writePhotosAlbum": {
          "desc": "需要您的授权才能保存文件"
        }
      },
      "requiredPrivateInfos": ["chooseFile"]
    }
    

Q3: 下载文件无法打开

  • 检查文件MIME类型
  • 添加Content-Disposition头:
    client.getObject({
      // ...
      ResponseHeaderOverrides: {
        'Content-Disposition': `attachment; filename="${encodeURIComponent(fileName)}"`
      }
    });
    

五、扩展功能建议

  1. 文件管理:实现文件夹分类、文件重命名
  2. 访问控制:设置私有读/公开读权限
  3. 图片处理:集成COS的图片处理参数(如?imageMogr2)
  4. 日志监控:通过CAM接口记录操作日志

总结

通过本文教程,你已掌握在UniApp中实现腾讯云COS存储的核心技术。完整流程可总结为:

  1. 准备COS存储资源
  2. 安全获取临时凭证
  3. 实现上传/下载/删除基础功能
  4. 优化性能与跨平台兼容性

💡 提示:生产环境建议将COS操作封装为独立模块,通过Promise链式调用管理异步流程。

参考文档

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐