Help & Documentation>Cloud Object Storage>Best Practice>Direct Data Upload>Practice of Direct Upload Through WeChat Mini Program

Practice of Direct Upload Through WeChat Mini Program

Last updated: 2023-09-12 18:28:49

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 characters
var camSafeUrlEncode = function (str) {
return encodeURIComponent(str)
.replace(/!/g, '%21')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29')
.replace(/\*/g, '%2A');
};

// Obtain Signature
var getAuthorization = function (options, callback) {
wx.request({
method: 'GET',
// Replace with your own server address to obtain the POST upload signature
url: '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 file
var uploadFile = function (filePath) {
var extIndex = filePath.lastIndexOf('.');
var fileExt = extIndex >= -1 ? filePath.substr(extIndex + 1) : '';
getAuthorization({ ext: fileExt }, function (AuthData) {
// Parameters used in the request
var prefix = 'https://' + AuthData.cosHost;
var key = AuthData.cosKey; // Allowing the server to determine the filename is more secure
var 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 file
wx.chooseMedia({
count: 1, // Default 9
sizeType: ['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 characters
var camSafeUrlEncode = function (str) {
return encodeURIComponent(str)
.replace(/!/g, '%21')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29')
.replace(/\*/g, '%2A');
};

// Obtain Signature
var getAuthorization = function (options, callback) {
wx.request({
method: 'GET',
// Replace with your own server address to obtain the PUT upload signature
url: '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 uploading
const 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 file
var 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 file
wx.chooseMedia({
count: 1, // Default 9
sizeType: ['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);
},
});
};

Documentation

If you need to use a Mini Program SDK, see Getting Started with Mini Program SDK.