简介

本文介绍如何不依赖 SDK,用简单的代码,在小程序直传文件到腾讯云COS的存储桶。

注意:

本文档内容基于 XML 版本的 API。

前期条件

  1. 登录 对象存储控制台 ,创建存储桶,设置 BucketName(存储桶名称) 和 Region(地域名称),详情请参见 创建存储桶 文档。
  2. 登录 访问管理控制台,进入 API 密钥管理页面,获取您的项目 SecretId 和 SecretKey。
注意:

目前腾讯云有COS特惠活动,新人1元起

实践步骤

1. 配置小程序域名白名单

小程序里请求腾讯云COS需要登录到微信公众平台,在“开发”->“开发设置”中,配置域名白名单。SDK 用到了两个接口:wx.uploadFile 和 wx.request。

  • cos.postObject 使用 wx.uploadFile 发送请求。
  • 其他方法使用 wx.request 发送请求。

两者都需要在对应白名单里,配置 COS 域名。白名单里配置的域名格式有两种:

  • 如果只用到一个存储桶,可以配置 Bucket 域名作为白名单域名,例如examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com
  • 如果用到多个存储桶,可以选择后缀式请求 COS,把 bucket 放在 pathname 里请求,这种方式需要配置地域域名作为白名单,例如cos.ap-guangzhou.myqcloud.com。具体可参考下文代码中的注释。

2. 获取临时密钥和计算签名

出于安全考虑,签名使用临时密钥,服务端搭建临时密钥服务,请参见 PHP 示例Nodejs 示例
如有其他语言或自行实现可参考以下流程:
(1)向服务端获取临时密钥,服务端首先使用固定密钥 SecretId、SecretKey 向 STS 服务获取临时密钥,得到临时密钥 tmpSecretId、tmpSecretKey、sessionToken,详情请参见 临时密钥生成及使用指引 或 cos-sts-sdk 。

注意:

根据使用的请求是put还是post,STS 的 policy action 要加上允许 "name/cos:PutObject"或"name/cos:PostObject"。

(2)前端通过 tmpSecretId、tmpSecretKey,以及 method、pathname 计算签名,可参考下文使用 cos-auth.js 来计算签名,如果业务需要也可以放在后端计算签名。
(3)将计算得到的签名和 sessionToken,分别放到

  • post请求的formData 的 Signature 和 x-cos-security-token 字段里,向 COS API 发出上传请求。
  • put请求的headers 的 Signature 和 x-cos-security-token 字段里,向 COS API 发出上传请求。
注意:

正式部署时服务端请加一层您的网站本身的权限检验。

3. 后缀式请求

COS API 一般的请求格式都类似POST http://examplebucket-1250000000.cos.ap-beijing.myqcloud.com/,请求的域名是存储桶域名。这样如果在小程序里用到多个存储桶,则需要配置这个存储桶域名作为白名单域名。解决方法如下:

COS 提供了后缀式请求格式POST http://cos.ap-beijing.myqcloud.com/examplebucket-1250000000/,请求的域名是地域域名,存储桶名称放在请求的路径里。在小程序里用到同一个地域多个存储桶,只需要配置一个域名cos.ap-beijing.myqcloud.com作为白名单域名。

后缀式请求格式需要注意,签名时使用的路径要用以存储桶名称作为前缀的路径,例如/examplebucket-1250000000/

4. 直传示例代码

以下代码同时举例了 PUT Object接口(推荐使用)和POST Object接口,操作指引如下:

 
var CosAuth = require('./cos-auth'); // 这里引用了 cos-auth.js,下载地址为 https://unpkg.com/cos-js-sdk-v5/demo/common/cos-auth.min.js 

var Bucket = 'examplebucket-1250000000';
var Region = 'ap-shanghai';
var ForcePathStyle = false; // 是否使用后缀式,涉及签名计算和域名白名单配置,后缀式说明看上文 var uploadFile = function () { // 请求用到的参数
var prefix = 'https://' + Bucket + '.cos.' + Region + '.myqcloud.com/';
if (ForcePathStyle) {
// 后缀式请求在签名时域名使用地域域名,而不是存储桶域名,具体说明见本文上述“3.后缀式请求”
prefix = 'https://cos.' + Region + '.myqcloud.com/' + Bucket + '/';
} // 对更多字符编码的 url encode 格式
var camSafeUrlEncode = function (str) {
return encodeURIComponent(str)
.replace(/!/g, '%21')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29')
.replace(/\*/g, '%2A');
}; // 获取临时密钥
var stsCache;
var getCredentials = function (callback) {
if (stsCache && Date.now() / 1000 + 30 < stsCache.expiredTime) {
callback(data.credentials);
return;
}
wx.request({
method: 'GET',
url: 'https://example.com/sts.php', // 服务端签名,参考上文说的获取临时密钥
dataType: 'json',
success: function (result) {
var data = result.data;
var credentials = data.credentials;
if (credentials) {
stsCache = data
} else {
wx.showModal({title: '临时密钥获取失败', content: JSON.stringify(data), showCancel: false});
}
callback(stsCache && stsCache.credentials);
},
error: function (err) {
wx.showModal({title: '临时密钥获取失败', content: JSON.stringify(err), showCancel: false});
}
});
}; // 计算签名
var getAuthorization = function (options, callback) {
getCredentials(function (credentials) {
callback({
XCosSecurityToken: credentials.sessionToken,
Authorization: CosAuth({
SecretId: credentials.tmpSecretId,
SecretKey: credentials.tmpSecretKey,
Method: options.Method,
Pathname: options.Pathname,
})
});
});
}; // post上传文件
var postFile = function (filePath) {
var Key = filePath.substr(filePath.lastIndexOf('/') + 1); // 这里指定上传的文件名
var signPathname = '/'; // PostObject 接口 Key 是放在 Body 传输,所以请求路径和签名路径是 /
if (ForcePathStyle) {
// 后缀式请求在签名时用的路径,要包含存储桶名称,具体说明见本文上述“3.后缀式请求”
signPathname = '/' + Bucket + '/';
}
getAuthorization({Method: 'POST', Pathname: signPathname}, function (AuthData) {
var requestTask = wx.uploadFile({
url: prefix,
name: 'file',
filePath: filePath,
formData: {
'key': Key,
'success_action_status': 200,
'Signature': AuthData.Authorization,
'x-cos-security-token': AuthData.XCosSecurityToken,
'Content-Type': '',
},
success: function (res) {
var url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
console.log(res.statusCode);
console.log(url);
if (/^2\d\d$/.test('' + res.statusCode)) {
wx.showModal({title: '上传成功', content: url, showCancel: false});
} else {
wx.showModal({title: '上传失败', content: JSON.stringify(res), showCancel: false});
}
},
fail: function (res) {
wx.showModal({title: '上传失败', content: JSON.stringify(res), showCancel: false});
}
});
requestTask.onProgressUpdate(function (res) {
console.log('进度:', res);
});
});
}; // put上传文件
var putFile = function (filePath) {
var Key = filePath.substr(filePath.lastIndexOf('/') + 1); // 这里指定上传的文件名
var signPathname = '/' + Key; // PutObject 接口 Key 是放在 url 传输,所以请求路径和签名路径是 /Key
if (ForcePathStyle) {
// 后缀式请求在签名时用的路径,要包含存储桶名称,具体说明见本文上述“3.后缀式请求”
signPathname = '/' + Bucket + '/' + Key;
}
getAuthorization({Method: 'PUT', Pathname: signPathname}, function (AuthData) {
// put请求需要从文件临时路径读取出文件内容
var wxfs = wx.getFileSystemManager();
wxfs.readFile({
filePath: filePath,
success: function (fileRes) {
var requestTask = wx.request({
url: prefix + signPathname.substr(signPathname.lastIndexOf('/') + 1),
method: 'PUT',
header: {
'Authorization': AuthData.Authorization,
'x-cos-security-token': AuthData.XCosSecurityToken,
},
data: fileRes.data,
success: function success(res) {
var url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
if (res.statusCode === 200) {
wx.showModal({title: '上传成功', content: url, showCancel: false});
} else {
wx.showModal({title: '上传失败', content: JSON.stringify(res), showCancel: false});
}
console.log(res.statusCode);
console.log(url);
},
fail: function fail(res) {
wx.showModal({title: '上传失败', content: JSON.stringify(res), showCancel: false});
},
});
requestTask.onProgressUpdate(function (res) {
console.log('正在进度:', res);
});
},
});
});
}; // 选择文件
wx.chooseImage({
count: 1, // 默认9
sizeType: ['original'], // 可以指定是原图还是压缩图,这里默认用原图
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
success: function (res) {
putFile(res.tempFiles[0].path); // put请求上传,推荐使用
// postFile(res.tempFiles[0].path); // post请求上传
}
})
};

用简单的代码,将小程序文件直传到腾讯云COS实践的更多相关文章

  1. 微信小程序/网站 上传图片到腾讯云COS

    COS简介: 腾讯云提供的一种对象存储服务,供开发者存储海量文件的分布式存储服务.可以将自己开发的应用的存储部分全部接入COS的存储桶中,有效减少应用服务器的带宽,请求等.个人也可以通过腾讯云账号免费 ...

  2. 微信小程序开发平台新功能「云开发」快速上手体验

    微信小程序开发平台刚刚开放了一个全新的功能:云开发. 简单地说就是将开发人员搭建微信小程序后端的成本再次降低,此文刚好在此产品公测时,来快速上手看看都有哪些方便开发者的功能更新. 微信小程序一直保持一 ...

  3. 微信小程序又一爆炸功能上线-云开发

    云开发介绍 开发者可以使用云开发开发微信小程序.小游戏,无需搭建服务器,即可使用云端能力. 云开发为开发者提供完整的云端支持,弱化后端和运维概念,无需搭建服务器,使用平台提供的 API 进行核心业务开 ...

  4. 微信小程序文件作用域模块引用

    文件作用域 在 JavaScript 文件中声明的变量和函数只在该文件中有效:不同的文件中可以声明相同名字的变量和函数,不会互相影响. 通过全局函数 getApp() 可以获取全局的应用实例,如果需要 ...

  5. 小程序文件上传uploadFile

    前台代码: bindPhoto(e) { var that = this; wx.chooseImage({ count: 1, sizeType: ['original','compressed'] ...

  6. Netty学习——基于netty实现简单的客户端聊天小程序

    Netty学习——基于netty实现简单的客户端聊天小程序 效果图,聊天程序展示 (TCP编程实现) 后端代码: package com.dawa.netty.chatexample; import ...

  7. Winfrom 简单的进度条小程序

    使用Winform空间编写简单的进度条小程序: 所需控件:Lable 标签  TextBox  文本框  progressBar  进度条控件  timer 定时器 下面是源码及效果图: /// &l ...

  8. 【腾讯Bugly干货分享】微信小程序开发思考总结——腾讯“信用卡还款”项目实践

    本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/58212d0fa7a7574c4f4cc3c5 作者:peggy 小程序概述 1 ...

  9. uniapp之uni-starter小程序多端研发框架搭建与项目实践

    随着移动互联网的飞速发展,无数移动APP琳琅满目:在移动App的发展的基础上,衍生了小程序.轻应用技术,它随时可用,但又无需安装卸载.小程序是一种不需要下载安装即可使用的应用,它实现了应用" ...

  10. uni-app微信小程序开发之引入腾讯视频小程序播放插件

    登录微信小程序管理后台添加腾讯视频播放插件: 正式开始使用腾讯视频小程序插件之前需先在微信公众平台 -> 第三方设置 -> 插件管理处添加插件,如下图所示: 在uni-app中引入插件代码 ...

随机推荐

  1. spring RedisTemplate用法

    1.maven依赖 <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis --&g ...

  2. vmware网络连接

    vmware提供桥接模式网络连接.网络地址转换 (NAT).仅主机模式网络连接和自定义网络连接选项,用于为虚拟机配置虚拟网络连接.在安装 vmware 时,已在主机系统中安装用于所有网络连接配置的软件 ...

  3. transformers 之Trainer对应的数据加载

    基础信息说明 本文以Seq2SeqTrainer作为实例,来讨论其模型训练时的数据加载方式 预训练模型:opus-mt-en-zh 数据集:本地数据集 任务:en-zh 机器翻译 数据加载 Train ...

  4. 一些excel随笔,瞎记一下

    1 使用sumif函数的时候,如果对于一列0求值返回的时候,显示一个英文中的破折号例 "-" ,是数字格式可能设置为了会计专用,改回数值就行,要逗号的话点其他格式里面的数值,找一下 ...

  5. Excel之VLOOKUP()函数的基本用法

    语法: VLOOKUP(lookup_value,table_array,col_index_num,[range_lookup]) 规则:  注意: 查找的值:内容需要完全一样 查找范围:查找范围的 ...

  6. 支持批量图片转文字的【OCR】文字识别工具,支持截图识别,速度快,准确度高,免费OCR,开源软件

    想必大家偶尔也有需要从图片中提取文字的需求,虽然现在手机上都自带了拍照识别功能,可是从电脑上的图片传到手机识别再将结果发回来实 在是有点麻烦,尤其当图片数量较多时,更是费时费力,使用网页版工具又要面临 ...

  7. Keil5 STM32 C++开发 ARM V6编译器的使用教程

    Keil5更新之后,开始支持ARM V6编译器,新版本的编译器对C++有了更多的支持,在编译方面也做了很多的改善,具体的没有详细了解,本文只是对STM32 开发下,使用V6版本的编译器进行STM32的 ...

  8. pve apt 更新

    解决pve6.2/pve6.3 安装ifupdown2,失败问题 https://www.cnblogs.com/lovesKey/p/14400874.html https://blog.whsir ...

  9. const char* str和const char str[]的区别

    首先,字符串常量是存储在flash中的.假设字符串常量在flash中的地址是0x8003fb8. 第一种方式,str等价于str的内存单元的地址,str的内存单元存储着字符串常量的地址 第二种方式,s ...

  10. 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转 JAVA

    package com.asiabasehk.cgg.util;   /**火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的互转  * Created by macremote on 1 ...