Feature Overview
This document describes how to use simple code to upload files to a COS bucket directly through a Weixin Mini Program without using an SDK.
Note
The content of this document is based on the XML version of the API.
Prerequisites
1. Log in to the Object Storage Console and create a bucket. Set the BucketName (bucket name) and Region (region name). For more information, see the Create Bucket document.
2. Log in to the CAM console and obtain your project's SecretId and SecretKey on the API key management page.
3. Configuring the Weixin Mini Program Allowlist
To request COS in your Weixin Mini Program, you need to log in to the Weixin Official Accounts Platform and configure the domain name allowlist in Development > Development Settings. The SDK uses two APIs: wx.uploadFile and wx.request.
For the cos.postObject method, requests are sent using wx.uploadFile.
For other methods, requests are sent using wx.request.
Both need to have the COS domain name configured in their respective whitelists. For example:
examplebucket-1250000000.cos.ap-guangzhou.myqcloud.com.Solution Description
Directions
1. Select a file in the frontend, and the frontend sends the file extension to the server.
2. The server generates a random COS file path with a timestamp based on the file extension and calculates the corresponding signature. It then returns the URL and signature information to the front-end.
3. The front-end uses PUT or POST requests to directly upload files to COS.
Solution strengths
Permission Security: Using server-side signatures can effectively limit the secure permission scope, allowing uploads to only a specified file path.
Path security: The server determines the random COS file path, which effectively avoids the problem of overwriting existing files and security risks.
Practical Steps
Configure Server-side Implementation for Signature Generation
Note
During the official deployment, please add a layer of your website's own permission verification to the server-side.
For information on how to calculate signatures, refer to the Request Signature document.
For server-side Node.js signature calculation code, refer to the Node.js Example.
Weixin Mini Program Upload Example
The following code demonstrates both the PUT Object (recommended) and POST Object interfaces, with operational guidance as follows:
Using POST for Uploads
var uploadFile = function () {// URL encode format for a wider range of charactersvar camSafeUrlEncode = function (str) {return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');};// Obtain Signaturevar getAuthorization = function (options, callback) {wx.request({method: 'GET',// Replace with your own server address to obtain the POST upload signatureurl: 'http://127.0.0.1:3000/post-policy?ext=' + options.ext,dataType: 'json',success: function (result) {var data = result.data;if (data) {callback(data);} else {wx.showModal({"title": "Temporary secret retrieval failed",content: JSON.stringify(data),showCancel: false,});}},error: function (err) {wx.showModal({"title": "Temporary secret retrieval failed",content: JSON.stringify(err),showCancel: false,});},});};var postFile = function ({ prefix, filePath, key, formData }) {var requestTask = wx.uploadFile({url: prefix,name: 'file',filePath: filePath,formData: formData,success: function (res) {var url = prefix + '/' + camSafeUrlEncode(key).replace(/%2F/g, '/');if (res.statusCode === 200) {wx.showModal({ title: 'Upload successful', content: url, showCancel: false });} else {wx.showModal({"title": "Upload failed",content: JSON.stringify(res),showCancel: false,});}console.log(res.header['x-cos-request-id']);console.log(res.statusCode);console.log(url);},fail: function (res) {wx.showModal({"title": "Upload failed",content: JSON.stringify(res),showCancel: false,});},});requestTask.onProgressUpdate(function (res) {console.log('Current progress:', res);});};// Upload filevar uploadFile = function (filePath) {var extIndex = filePath.lastIndexOf('.');var fileExt = extIndex >= -1 ? filePath.substr(extIndex + 1) : '';getAuthorization({ ext: fileExt }, function (AuthData) {// Parameters used in the requestvar prefix = 'https://' + AuthData.cosHost;var key = AuthData.cosKey; // Allowing the server to determine the filename is more securevar formData = {key: key,success_action_status: 200,'Content-Type': '','q-sign-algorithm': AuthData.qSignAlgorithm,'q-ak': AuthData.qAk,'q-key-time': AuthData.qKeyTime,'q-signature': AuthData.qSignature,policy: AuthData.policy,};if (AuthData.securityToken)formData['x-cos-security-token'] = AuthData.securityToken;postFile({ prefix, filePath, key, formData });});};// Select a filewx.chooseMedia({count: 1, // Default 9sizeType: ['original'], // Specifies whether to use the original image or a compressed version; the default is the original image.sourceType: ['album', 'camera'], // Specify the source as either album or camera; both are available by default.success: function (res) {uploadFile(res.tempFiles[0].tempFilePath);},});};
Using PUT for Upload
var uploadFile = function () {// URL encode format for a wider range of charactersvar camSafeUrlEncode = function (str) {return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/\*/g, '%2A');};// Obtain Signaturevar getAuthorization = function (options, callback) {wx.request({method: 'GET',// Replace with your own server address to obtain the PUT upload signatureurl: 'http://127.0.0.1:3000/put-sign?ext=' + options.ext,dataType: 'json',success: function (result) {var data = result.data;if (data) {callback(data);} else {wx.showModal({"title": "Temporary secret retrieval failed",content: JSON.stringify(data),showCancel: false,});}},error: function (err) {wx.showModal({"title": "Temporary secret retrieval failed",content: JSON.stringify(err),showCancel: false,});},});};var putFile = function ({ prefix, filePath, key, AuthData }) {// Put upload requires reading the actual content of the file for uploadingconst wxfs = wx.getFileSystemManager();wxfs.readFile({filePath: filePath,success: function (fileRes) {var requestTask = wx.request({url: prefix + '/' + key,method: 'PUT',header: {Authorization: AuthData.authorization,'x-cos-security-token': AuthData.securityToken,},data: fileRes.data,success: function success(res) {var url = prefix + '/' + camSafeUrlEncode(key).replace(/%2F/g, '/');if (res.statusCode === 200) {wx.showModal({"title": "Upload successful",content: url,showCancel: false,});} else {wx.showModal({"title": "Upload failed",content: JSON.stringify(res),showCancel: false,});}console.log(res.statusCode);console.log(url);},fail: function fail(res) {wx.showModal({"title": "Upload failed",content: JSON.stringify(res),showCancel: false,});},});requestTask.onProgressUpdate(function (res) {console.log('Current progress:', res);});},});};// Upload filevar uploadFile = function (filePath) {var extIndex = filePath.lastIndexOf('.');var fileExt = extIndex >= -1 ? filePath.substr(extIndex + 1) : '';getAuthorization({ ext: fileExt }, function (AuthData) {const prefix = 'https://' + AuthData.cosHost;const key = AuthData.cosKey;putFile({ prefix, filePath, key, AuthData });});};// Select a filewx.chooseMedia({count: 1, // Default 9sizeType: ['original'], // Specifies whether to use the original image or a compressed version; the default is the original image.sourceType: ['album', 'camera'], // Specify the source as either album or camera; both are available by default.success: function (res) {uploadFile(res.tempFiles[0].tempFilePath);},});};