手把手教你如何通过微信小程序上传图片到腾讯云COS

引言

随着移动互联网的发展,微信小程序因其便捷性和易用性而广受欢迎。在许多应用场景中,用户需要上传图片来完成特定任务,如头像设置、商品发布等。本文将详细介绍如何利用微信小程序实现图片上传到腾讯云的COS(Cloud Object Storage,对象存储)服务,帮助开发者快速掌握这一技能。

准备工作

  1. 注册腾讯云账号并开通COS服务

    • 登录腾讯云官网并注册账号。
    • 在控制台中找到“对象存储COS”服务并开通。
    • 创建一个存储桶(Bucket),选择合适的地域和权限配置(建议测试阶段使用公有读私有写权限)。
    • 获取存储桶名称(Bucket Name)、地域(Region)和密钥信息(SecretId 和 SecretKey)。
  2. 创建微信小程序

    • 登录微信公众平台,注册并创建一个新的小程序项目。
    • 获取小程序的AppID和AppSecret。
  3. 配置服务器域名

    • 在微信小程序管理后台,进入“开发设置”,添加腾讯云COS的API域名,例如:
      https://cos.<region>.myqcloud.com
  4. 安装腾讯云COS SDK

    • 腾讯云提供了官方的JavaScript SDK,支持Node.js和其他环境。由于微信小程序无法直接引入大型库,我们需要使用轻量级的HTTP请求方式来完成上传操作。

 或者 其他使用的话直接引入cos-js-sdk-v5.min.js文件也可以,小程序的话下载完记得构建一下

具体实现

方式一:直接使用永久密钥

原理

  • 永久密钥:直接使用腾讯云账号的SecretIdSecretKey进行签名。
  • 优点:实现简单,适合快速开发和测试。
  • 缺点:安全性较低,密钥暴露后可能导致数据泄露,因此不推荐在生产环境中使用。

实现步骤

  1. 配置永久密钥

    • 在小程序前端代码中直接嵌入SecretIdSecretKey
    • 注意:这种方式仅适用于测试环境,生产环境中应避免直接暴露密钥。
  2. 代码示例

app.js

App({
  globalData: {
    cosConfig: {
      bucket: 'your-bucket-name', // 替换为你的存储桶名称
      region: 'ap-guangzhou',     // 替换为你的存储桶地域
      secretId: 'your-secret-id', // 替换为你的SecretId
      secretKey: 'your-secret-key' // 替换为你的SecretKey
    }
  }
});

index.wxml

<view class="container">
  <button bindtap="chooseImage">选择图片</button>
  <image wx:if="{{tempFilePath}}" src="{{tempFilePath}}" mode="aspectFit"></image>
</view>

index.js

import COS from "cos-wx-sdk-v5";

const app = getApp();

Page({
  data: {
    tempFilePath: '', // 图片本地路径
    cos: null         // COS实例
  },

  onLoad() {
    // 初始化COS实例
    this.setData({
      cos: new COS({
        getAuthorization: (options, callback) => {
          const authorization = this.generatePermanentSignature();
          callback(authorization);
        }
      })
    });
  },

  chooseImage() {
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: (res) => {
        const tempFilePath = res.tempFilePaths[0];
        this.setData({ tempFilePath });
        this.uploadFileToCOS(tempFilePath);
      }
    });
  },

  uploadFileToCOS(filePath) {
    const { cos } = this.data;
    const { bucket, region } = app.globalData.cosConfig;

    cos.putObject({
      Bucket: bucket,
      Region: region,
      Key: `uploads/${Date.now()}.jpg`, // 文件名,可自定义
      FilePath: filePath,               // 本地文件路径
      onProgress: (progressData) => {
        console.log('上传进度:', progressData.percent * 100 + '%');
      }
    }, (err, data) => {
      if (err) {
        console.error('上传失败:', err);
        wx.showToast({ title: '上传失败', icon: 'none' });
      } else {
        console.log('上传成功:', data);
        wx.showToast({ title: '上传成功', icon: 'success' });
      }
    });
  },

  generatePermanentSignature() {
    const { secretId, secretKey } = app.globalData.cosConfig;
    const now = Math.floor(Date.now() / 1000);
    const expiredTime = now + 60; // 签名有效期60秒
    const keyTime = `${now};${expiredTime}`;
    const signKey = this.hmacSha1(secretKey, keyTime);
    const stringToSign = `sha1\n${keyTime}\n`;
    const signature = this.hmacSha1(signKey, stringToSign);

    return {
      TmpSecretId: secretId,
      TmpSecretKey: secretKey,
      XCosSecurityToken: '',
      StartTime: now,
      ExpiredTime: expiredTime,
      Signature: signature
    };
  },

  hmacSha1(key, message) {
    // HMAC-SHA1加密算法(实际开发中建议使用后端生成签名)
    const crypto = require('crypto');
    return crypto.createHmac('sha1', key).update(message).digest('hex');
  }
});

方式二:使用临时密钥(推荐)

原理

  • 临时密钥:通过腾讯云STS(安全凭证服务)生成临时的TmpSecretIdTmpSecretKeySessionToken
  • 优点:安全性高,密钥具有时效性,即使泄露也不会长期影响系统安全。
  • 缺点:需要搭建后端服务来生成临时密钥。

实现步骤

  1. 后端生成临时密钥

    使用腾讯云SDK,在后端调用STS接口生成临时密钥。

 index.html和上面一致

 index.js

import COS from "cos-wx-sdk-v5";

const app = getApp();

Page({
  data: {
    tempFilePath: '',
    cos: null
  },

  onLoad() {
    this.setData({
      cos: new COS({
        getAuthorization: (options, callback) => {
          wx.request({
            url: 'http://localhost:3000/get-temp-keys', // 替换为你的后端接口地址
            method: 'GET',
            success: (res) => {
              const { credentials } = res.data;
              callback({
                TmpSecretId: credentials.tmpSecretId,
                TmpSecretKey: credentials.tmpSecretKey,
                XCosSecurityToken: credentials.sessionToken,
                StartTime: credentials.startTime,
                ExpiredTime: credentials.expiredTime
              });
            },
            fail: () => {
              console.error('获取临时密钥失败');
            }
          });
        }
      })
    });
  },

  chooseImage() {
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: (res) => {
        const tempFilePath = res.tempFilePaths[0];
        this.setData({ tempFilePath });
        this.uploadFileToCOS(tempFilePath);
      }
    });
  },

  uploadFileToCOS(filePath) {
    const { cos } = this.data;
    const { bucket, region } = app.globalData.cosConfig;

    cos.putObject({
      Bucket: bucket,
      Region: region,
      Key: `uploads/${Date.now()}.jpg`,
      FilePath: filePath,
      onProgress: (progressData) => {
        console.log('上传进度:', progressData.percent * 100 + '%');
      }
    }, (err, data) => {
      if (err) {
        console.error('上传失败:', err);
        wx.showToast({ title: '上传失败', icon: 'none' });
      } else {
        console.log('上传成功:', data);
        wx.showToast({ title: '上传成功', icon: 'success' });
      }
    });
  }
});

封装方式

cos.js

import COS from "cos-wx-sdk-v5";
import { getCosAccesstoekn } from "../api/module/cos"; // 获取临时密钥接口

let cos = null;

// 获取临时密钥
const getCosInstance = () => {
  return new Promise(async (resolve, reject) => {
    const res = await getCosAccesstoekn();
    console.log(res, "cos");


    if (res.code != 200) {
      reject("获取 STS 失败");
      return;
    }

    const { credentials, startTime, expiredTime } = res.data;
    cos = new COS({
      getAuthorization: (options, callback) => {
        callback({
          TmpSecretId: credentials.tmpSecretId,
          TmpSecretKey: credentials.tmpSecretKey,
          SecurityToken: credentials.sessionToken,
          StartTime: startTime,
          ExpiredTime: expiredTime
        });
      },
    });
    resolve(cos);
  });
}

const uploadFileToCOS = async (filePath, cloudPath) => {
  try {
    // 获取 COS 实例
    const cos = await getCosInstance();

    // 调用 putObject 方法上传文件
    return new Promise((resolve, reject) => {
      cos.putObject(
        {
          Bucket: "*******", // 替换为你的存储桶名称
          Region: "******",      // 替换为你的存储桶所在区域
          Key: cloudPath,             // 文件在 COS 上的路径(包括文件名)
          FilePath: filePath,         // 本地文件路径(微信小程序中的临时文件路径)
          Headers: {
            'Content-Disposition': encodeURI('inline')
          },
          onProgress: function (progressData) {
            console.log(JSON.stringify(progressData));
          },
        },
        (err, data) => {
          if (err) {
            console.error("上传失败:", err);
            reject(err);
          } else {
            console.log("上传成功:", data);
            const url = `https://${data.Location}`
            resolve(url);
          }
        }
      );
    });
  } catch (error) {
    console.error("获取 COS 实例失败:", error);
    throw error;
  }
};


export {
  uploadFileToCOS
};

index.js

// 上传图片
  async uploadImage(filePath) {
    wx.showLoading({ title: "上传中..." });

    try {
      const fileName = `uploads/${Date.now()}-${Math.random().toString(36).substr(2, 5)}.png`;

      const cos = await uploadFileToCOS(filePath, fileName);
      console.log(cos);
      this.setData({ imageUrl: cos });

      wx.hideLoading();
    } catch (error) {
      wx.hideLoading();
      console.error("获取 STS 失败", error);
      wx.showToast({ title: "获取权限失败", icon: "error" });
    }
  },

思路

封装的目标

这段代码的主要目标是:

  • 抽象化:将复杂的腾讯云COS SDK操作封装成一个简单的函数uploadFileToCOS,开发者只需调用这个函数即可完成文件上传。
  • 模块化:通过分离临时密钥获取逻辑和文件上传逻辑,提高代码的可维护性和复用性。
  • 安全性:使用临时密钥(STS)进行认证,避免直接暴露永久密钥。

核心封装逻辑
(1) 获取临时密钥
  • 腾讯云COS要求在上传文件时提供身份认证信息(如SecretIdSecretKeySessionToken等)。为了保证安全性,推荐使用临时密钥(STS)代替永久密钥。
  • 代码中通过getCosAccesstoekn接口从后端获取临时密钥,并将其传递给腾讯云COS SDK。

关键点:

  • getCosInstance是一个返回Promise的函数,用于初始化COS实例。
  • getAuthorization回调中,将临时密钥(TmpSecretIdTmpSecretKeySecurityToken)传递给COS SDK。
  • 如果临时密钥获取失败(如接口返回非200状态码),会抛出错误并终止流程。
(2) 文件上传逻辑
  • uploadFileToCOS是封装好的文件上传函数,接收两个参数:
    • filePath:本地文件路径(通常是微信小程序选择图片后生成的临时文件路径)。
    • cloudPath:文件在COS上的存储路径(包括文件名)。
  • 函数内部调用putObject方法完成文件上传。

关键点:

  • 使用cos.putObject上传文件,支持进度监听(onProgress)。
  • 上传成功后,返回文件的访问URL(https://${data.Location}),方便前端直接使用。
  • 如果上传失败,会捕获错误并抛出异常。

总结

  • 直接密钥:适合快速开发和测试,但存在安全隐患,不适合生产环境。
  • 临时密钥:安全性高,推荐用于生产环境,但需要搭建后端服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值