注:前端微信小程序,使用LinUI组件辅助设计(详见官网),后端是springboot。

效果展示:

1. 界面展示

2. 上传文件时选择文件夹

3. 进度条展示

4. 上传成功展示

5. 上传成功返回链接

微信小程序源码

uploadVideo.wxml

<view class="button" bind:lintap="tap">
  <l-button type="success">上传</l-button>
</view>
<view class="progress">
  <l-progress percent="{{percent}}" active-color="#34bfa3"></l-progress>
</view>
<l-toast
  show="{{success}}"
  icon="success"
  title="上传成功!"
/>

uploadVideo.js

var COS = require('cos-wx-sdk-v5')
var cos = new COS({
  // ForcePathStyle: true, // 如果使用了很多存储桶,可以通过打开后缀式,减少配置白名单域名数量,请求时会用地域域名
  SimpleUploadMethod: 'putObject', // 强烈建议,高级上传、批量上传内部对小文件做简单上传时使用putObject,sdk版本至少需要v1.3.0
  getAuthorization: function (options, callback) {
      // 初始化时不会调用,只有调用 cos 方法(例如 cos.putObject)时才会进入
      // 异步获取临时密钥
      wx.request({
          url: 'http://127.0.0.1:8080/authorization',
          dataType: 'json',
          success: function (result) {
              var data = JSON.parse(result.data);
              console.log(data)
              callback({
                  TmpSecretId: data.Credentials.TmpSecretId,
                  TmpSecretKey: data.Credentials.TmpSecretKey,
                  // v1.2.0之前版本的 SDK 使用 XCosSecurityToken 而不是 SecurityToken
                  SecurityToken: data.Credentials.Token,
                  // 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
                  // StartTime: data.startTime, // 时间戳,单位秒,如:1580000000
                  ExpiredTime: data.ExpiredTime, // 时间戳,单位秒,如:1580000900
              });
          }
      });
  }
});
Page({
  data: {
    percent: 0,
    success: false
  },
  tap: function(){
    var that = this
    wx.chooseMedia({
      count: 1,
      mediaType: ['image','video'],
      sourceType: ['album'],
      success: res=>{
        var fileName = Date.now() + '.' + res.tempFiles[0].tempFilePath.split('.')[1]
        cos.uploadFile({
          Bucket: 'flow-1309139497', /* 填写自己的 bucket,必须字段 */
          Region: 'ap-shanghai',     /* 存储桶所在地域,必须字段 */
          Key: fileName,          /* 存储在桶里的对象键(例如:1.jpg,a/b/test.txt,图片.jpg)支持中文,必须字段 */
          FilePath: res.tempFiles[0].tempFilePath, /* 上传文件路径,必须字段 */
          SliceSize: 1024 * 1024 * 5,     /* 触发分块上传的阈值,超过5MB使用分块上传,小于5MB使用简单上传。可自行设置,非必须 */
          onProgress: function(progressData) {
            that.setData({
              percent: progressData.percent * 100
            })
          }
        }, function(err, data) {
          if (err) {
            console.log('上传失败', err);
          } else {
            that.setData({
              success: true,
              percent: 0
            })
            console.log('https://' + data.Location)
          }
        })
      }
    })
  },
})

uploadVideo.wxss

.button{
  margin-top: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.progress{
  width: 300rpx;
  text-align: center;
  margin-top: 10%;
  margin-left: 30%;
}

uploadVideo.json

{
  "usingComponents": {}
}
注:以上代码用到了LinUi,请参考官方文档提前导入

SpringBoot源码

注:此为controller层,官网获取Credential里的SecretId和SecretKey并填入。
访问密钥 - 控制台 (tencent.com)
流程解析:后端通过获取临时秘钥给到小程序,小程序再携带这个秘钥进行文件的上传。
package com.flow.api;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sts.v20180813.StsClient;
import com.tencentcloudapi.sts.v20180813.models.GetFederationTokenRequest;
import com.tencentcloudapi.sts.v20180813.models.GetFederationTokenResponse;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AuthorizationApi {
    @GetMapping("/authorization")
    public String getAuthorization(){
        GetFederationTokenResponse resp = new GetFederationTokenResponse();
        try{
            // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
            Credential cred = new Credential("xxxxxxxxxx", "xxxxxxxx");
            // 实例化一个http选项,可选的,没有特殊需求可以跳过
            HttpProfile httpProfile = new HttpProfile();
            httpProfile.setEndpoint("sts.tencentcloudapi.com");
            // 实例化一个client选项,可选的,没有特殊需求可以跳过
            ClientProfile clientProfile = new ClientProfile();
            clientProfile.setHttpProfile(httpProfile);
            // 实例化要请求产品的client对象,clientProfile是可选的
            StsClient client = new StsClient(cred, "ap-shanghai", clientProfile);
            // 实例化一个请求对象,每个接口都会对应一个request对象
            GetFederationTokenRequest req = new GetFederationTokenRequest();
            req.setName("auth");
            req.setPolicy(JSONObject.toJSONString(getPolicy()));

            // 返回的resp是一个GetFederationTokenResponse的实例,与请求对象对应
            resp = client.GetFederationToken(req);
        } catch (TencentCloudSDKException e) {
            System.out.println(e.toString());
        }
        return GetFederationTokenResponse.toJsonString(resp);
    }


    public JSONObject getPolicy(){
        //第一层
        JSONObject config = new JSONObject();
        config.put("version", "2.0");
        //第二层
        JSONArray config_2 = new JSONArray();
        config.put("statement", config_2);
        //第三层
        JSONObject config_3 = new JSONObject();
        config_2.add(config_3);
        //第四层
        JSONArray config_4 = new JSONArray();
        config_4.add("*");
        config_3.put("action", config_4);
        //第五层
        JSONArray config_5 = new JSONArray();
        config_5.add("*");
        config_3.put("resource", config_5);
        return config;
    }
}
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐