cos-js-sdk-v5
Version:
JavaScript SDK for [腾讯云对象存储](https://cloud.tencent.com/product/cos)
1,820 lines (1,780 loc) • 176 kB
JavaScript
/**
* @jest-environment jsdom
*/
import { describe, expect, jest, test } from '@jest/globals';
import COS from '../index.js';
// config 替换成自己的桶信息
var config = {
SecretId: process.env.SecretId,
SecretKey: process.env.SecretKey,
Bucket: process.env.Bucket, // 需提前创建并设置跨域
Region: process.env.Region,
ReplicationBucket: process.env.ReplicationBucket, // 存储桶复制时用到的桶,需提前创建并设置跨域
ReplicationRegion: process.env.ReplicationRegion, // 存储桶复制时用到的桶的地域
Uin: process.env.Uin,
};
// mock localStroage
var localStorageMock = (function () {
var store = {};
return {
getItem: function (key) {
return store[key];
},
setItem: function (key, value) {
store[key] = value.toString();
},
clear: function () {
store = {};
},
removeItem: function (key) {
delete store[key];
},
};
})();
Object.defineProperty(window, 'localStorage', {
writable: true,
configurable: true,
value: localStorageMock,
});
function checkEnvParams() {
if (!process.env.Bucket) {
console.warn('环境变量里未找到Bucket,请检查');
return;
}
if (!process.env.Region) {
console.warn('环境变量里未找到Region,请检查');
return;
}
if (!process.env.ReplicationBucket) {
console.warn('环境变量里未找到ReplicationBucket,请检查');
return;
}
if (!process.env.ReplicationRegion) {
console.warn('环境变量里未找到ReplicationRegion,请检查');
return;
}
if (!process.env.Uin) {
console.warn('环境变量里未找到Uin,请检查');
return;
}
return true;
}
var util = {
createFile: function (options) {
var buffer = new ArrayBuffer(options.size || 0);
var arr = new Uint8Array(buffer);
for (var i = 0; i < arr.length; i++) {
arr[i] = 0;
}
var opt = {};
options.type && (opt.type = options.type);
var blob = new Blob([buffer], options);
return blob;
},
str2blob: function (str) {
var size = str.length;
var buffer = new ArrayBuffer(size || 0);
var arr = new Uint8Array(buffer);
for (var i = 0; i < arr.length; i++) {
arr[i] = str[i];
}
var blob = new Blob([buffer]);
return blob;
},
};
function camSafeUrlEncode(str) {
return encodeURIComponent(str)
.replace(/!/g, '%21')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29')
.replace(/\*/g, '%2A');
}
function comparePlainObject(a, b) {
if (Object.keys(a).length !== Object.keys(b).length) {
return false;
}
for (var key in a) {
if (typeof a[key] === 'object' && typeof b[key] === 'object') {
if (!comparePlainObject(a[key], b[key])) {
return false;
}
} else if (a[key] != b[key]) {
return false;
}
}
return true;
}
function prepareBigObject(needHeaders) {
return new Promise(function (resolve, reject) {
// 创建测试文件
var filename = name || 'bigger.zip';
var content = util.createFile({ size: 1024 * 1024 * 10 });
var put = function () {
// 调用方法
var params = {
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: content,
ContentLength: content.length,
};
if (needHeaders) {
params.ContentType = 'text/html';
params.CacheControl = 'max-age=7200';
params.ContentDisposition = 'inline;filename=hello.jpg';
params.Expires = new Date().toGMTString();
params.Headers = {
'x-cos-meta-test': 'xxx',
};
}
cos.putObject(params, function (err, data) {
err ? reject(err) : resolve();
});
};
put();
});
}
var createFileSync = function (size) {
return util.createFile({ size: size });
};
var dataURItoUploadBody = function (dataURI) {
var byteString = atob(dataURI.split(',')[1]);
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], { type: mimeString });
};
var getAuthorization = function (options, callback) {
var authorization = COS.getAuthorization({
SecretId: process.env.SecretId,
SecretKey: process.env.SecretKey,
Method: options.Method,
Pathname: options.Pathname,
Query: options.Query,
Headers: options.Headers,
Expires: 900,
});
callback({
Authorization: authorization,
});
};
var cos = new COS({
// 必选参数
SecretId: config.SecretId,
SecretKey: config.SecretKey,
UploadCheckContentMd5: true,
UploadAddMetaMd5: true,
Protocol: 'http:',
// getAuthorization: getAuthorization,
});
var tempCOS = new COS({
getAuthorization: function (options, callback) {
var url = 'http://9.134.125.65:3333/sts'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function (e) {
try {
var data = JSON.parse(e.target.responseText);
var credentials = data.credentials;
} catch (e) {}
if (!data || !credentials) {
return logger.error('credentials invalid:\n' + JSON.stringify(data, null, 2));
}
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
SecurityToken: credentials.sessionToken,
StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000000
ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
});
};
xhr.send(JSON.stringify(options.Scope));
},
});
// 临时密钥允许的路径
var tempCOSPrefix = 'js-sdk/test/';
var Bucket = config.Bucket;
var BucketShortName = Bucket;
var TaskId;
var AppId;
var BucketLongName = Bucket + '-' + AppId;
var match = config.Bucket.match(/^(.+)-(\d+)$/);
if (match) {
BucketLongName = config.Bucket;
BucketShortName = match[1];
AppId = match[2];
}
var group = function (name, fn) {
if (!checkEnvParams()) return;
console.log(`${name}进行中....`);
describe(name, function () {
jest.setTimeout(2 * 60 * 1000);
fn.apply(this, arguments);
});
};
var assert = {
ok: function (val) {
expect(Boolean(val)).toBeTruthy();
},
};
group('init cos', function () {
const putFile = function (cosIns, done, canSuccess = true) {
var key = '1.txt';
var content = Date.now().toString();
cosIns.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
Headers: {
'x-cos-test': '1',
'x-cos-meta-test': 'meta',
},
'x-cos-test2': '2',
},
function (err, data) {
assert.ok(canSuccess ? !err : err);
done();
},
);
};
test('使用AppId', function (done) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
AppId: AppId,
});
putFile(initCos, done);
});
test('SecretId格式错误', function (done) {
var initCos = new COS({
SecretId: config.SecretId + ' ',
SecretKey: config.SecretKey,
});
putFile(initCos, done, false);
});
test('SecretKey格式错误', function (done) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey + ' ',
});
putFile(initCos, done, false);
});
test('Timeout=6000', function (done) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Timeout: 6000,
});
putFile(initCos, done);
});
test('ForcePathStyle', function (done) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
ForcePathStyle: true,
});
putFile(initCos, done, true);
});
test('getAuthorization error tmpSecretId', function (done) {
var initCos = new COS({
getAuthorization: function (options, callback) {
callback({
tmpSecretId: config.SecretId,
TmpSecretKey: config.SecretKey,
});
},
});
putFile(initCos, done, false);
});
test('getAuthorization error tmpSecretKey', function (done) {
var initCos = new COS({
getAuthorization: function (options, callback) {
callback({
TmpSecretId: config.SecretId,
tmpSecretKey: config.SecretKey,
});
},
});
putFile(initCos, done, false);
});
test('getAuthorization error', function (done) {
var initCos = new COS({
getAuthorization: function (options, callback) {
callback({
TmpSecretId: config.SecretId,
TmpSecretKey: config.SecretKey,
});
},
});
putFile(initCos, done, false);
});
test('getAuthorization 使用临时密钥 putObject', function (done) {
tempCOS.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: tempCOSPrefix + Date.now().toString(36),
Body: '12345',
},
function (err, data) {
assert.ok(!err);
done();
},
);
});
test('getAuthorization 使用临时密钥 sliceUploadFile', function (done) {
const file = createFileSync(20 * 1024 * 1024);
tempCOS.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: tempCOSPrefix + Date.now().toString(36),
Body: file,
},
function (err, data) {
assert.ok(!err);
done();
},
);
});
test('getAuthorization 使用临时密钥 sliceUploadFile 没有权限', function (done) {
const file = createFileSync(20 * 1024 * 1024);
tempCOS.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Date.now().toString(36),
Body: file,
},
function (err, data) {
assert.ok(err);
done();
},
);
});
});
group('task 队列', function () {
test('putObject() 批量上传', function (done) {
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
UploadQueueSize: 100,
});
var upload = function () {
var filename = '5.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: '12345',
},
function (err, data) {},
);
};
for (var i = 0; i < 120; i++) {
upload();
}
var taskList = cos.getTaskList();
const isUploading = cos.isUploadRunning();
assert.ok(isUploading);
done();
});
test('putObject(),update-list()', function (done) {
var filename = '10m.zip';
const file = createFileSync(10 * 1024 * 1024);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: file,
},
function (err, data) {
assert.ok(!err);
done();
},
);
cos.on('task-list-update', function () {});
});
});
group('getService()', function () {
var cos = new COS({
// 必选参数
SecretId: config.SecretId,
SecretKey: config.SecretKey,
UploadCheckContentMd5: true,
UploadAddMetaMd5: true,
Protocol: 'http:',
ServiceDomain: 'service.cos.myqcloud.com/',
});
test('getService 老用法', function (done) {
cos.getService(function (err, data) {
assert.ok(err);
done();
});
});
test('getService 传Region', function (done) {
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
});
cos.getService(
{
Region: config.Region,
},
function (err, data) {
assert.ok(err);
done();
},
);
});
test('getService 不传Region和Domain', function (done) {
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
});
cos.getService({}, function (err, data) {
assert.ok(err);
done();
});
});
test('不能正常列出 Bucket', function (done) {
cos.getService(
{
Region: config.Region,
},
function (err, data) {
assert.ok(err);
done();
},
);
});
});
group('putBucket()', function () {
var NewBucket = 'test' + Date.now().toString(36) + '-' + AppId;
test('创建 bucket js sdk因为跨域会失败', function (done) {
cos.putBucket(
{
Bucket: NewBucket,
Region: config.Region,
},
function (err, data) {
assert.ok(err);
done();
},
);
});
test('正常创建 bucket BucketAZConfig js sdk因为跨域会失败', function (done) {
cos.putBucket(
{
Bucket: NewBucket,
Region: config.Region,
BucketAZConfig: {},
},
function (err, data) {
assert.ok(err);
done();
},
);
});
test('deleteBucket() deleteBucket 不存在', function (done) {
cos.deleteBucket(
{
Bucket: config.Bucket + Date.now().toString(36),
Region: config.Region,
},
function (err, data) {
assert.ok(err, 'deleteBucket 不存在');
done();
},
);
});
});
group('mock readAsBinaryString', function () {
test('mock readAsBinaryString', function (done) {
FileReader.prototype._readAsBinaryString = FileReader.prototype.readAsBinaryString;
FileReader.prototype.readAsBinaryString = false;
var filename = '10m.zip';
var blob = util.createFile({ size: 1024 * 1024 * 10 });
var paused = false;
cos.sliceUploadFile({
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
if (!paused && info.percent > 0.6) {
cos.cancelTask(TaskId);
var hasProgress = false;
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
if (info.percent === 0) return;
expect(info.percent).toBeGreaterThanOrEqual(0.3);
cos.cancelTask(TaskId);
FileReader.prototype.readAsBinaryString = FileReader.prototype._readAsBinaryString;
delete FileReader.prototype._readAsBinaryString;
done();
},
},
function (err) {
if (hasProgress) {
done();
}
},
);
}
},
});
});
});
group('getAuth()', function () {
test('getAuth()', function (done) {
var content = Date.now().toString();
var key = '1.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
cos.getAuth(
{
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Method: 'get',
Key: key,
Scope: [
{
action: 'GetObject',
bucket: config.Bucket,
region: config.Region,
prefix: key,
},
],
},
function (AuthData) {
if (typeof AuthData === 'string') {
AuthData = { Authorization: AuthData };
}
if (!AuthData.Authorization) {
AuthData.Authorization = COS.getAuthorization({
SecretId: AuthData.TmpSecretId,
SecretKey: AuthData.TmpSecretKey,
Method: 'get',
Key: key,
SystemClockOffset: cos.options.SystemClockOffset,
});
}
var link =
'http://' +
config.Bucket +
'.cos.' +
config.Region +
'.myqcloud.com' +
'/' +
camSafeUrlEncode(key).replace(/%2F/g, '/') +
'?' +
AuthData.Authorization +
(AuthData.SecurityToken ? '&x-cos-security-token=' + AuthData.SecurityToken : '');
done();
},
);
},
);
});
});
group('getObjectUrl()', function () {
test('getObjectUrl()', function (done) {
var content = Date.now().toString();
var key = '1.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
cos.getObjectUrl(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Query: {
a: 1,
},
Sign: false,
},
function (err, data) {
expect(typeof data.Url).toBe('string');
err ? done(err) : done();
},
);
},
);
});
});
group('auth check', function () {
test('auth check', function (done) {
cos.getBucket(
{
Bucket: config.Bucket,
Region: config.Region,
Prefix: 'aksjhdlash sajlhj!@#$%^&*()_+=-[]{}\';:"/.<>?.,??sadasd#/.,/~`',
Headers: {
'x-cos-test': 'aksjhdlash sajlhj!@#$%^&*()_+=-[]{}\';:"/.<>?.,??sadasd#/.,/~`',
},
},
function (err, data) {
err ? done(err) : done();
},
);
});
});
group('getBucket(),listObjectVersions()', function () {
test('正常获取 bucket 里的文件列表', function (done) {
cos.getBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
expect(data.Name).toBe(BucketLongName);
expect(data.Contents).toBeInstanceOf(Array);
err ? done(err) : done();
},
);
});
test('正常获取 bucket 里的文件版本列表', function (done) {
cos.listObjectVersions(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
expect(data.Name).toBe(config.Bucket);
expect(data.Versions).toBeInstanceOf(Array);
err ? done(err) : done();
},
);
});
});
group('putObject(),cancelTask()', function () {
test('putObject(),cancelTask()', function (done) {
var filename = '10m.zip';
var alive = false;
var canceled = false;
const file = createFileSync(10 * 1024 * 1024);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: file,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
alive = true;
if (!canceled) {
cos.cancelTask(TaskId);
alive = false;
canceled = true;
setTimeout(function () {
expect(alive).toBe(false);
done();
}, 1200);
}
},
},
function (err, data) {
alive = true;
err ? done(err) : done();
},
);
});
});
group('putObject 测试老参数', function () {
test('putObject() BucketShortName', function (done) {
var filename = '1m.zip';
const file = createFileSync(1 * 1024 * 1024);
cos.putObject(
{
Bucket: BucketShortName,
AppId: AppId,
Region: config.Region,
Key: filename,
Body: file,
},
function (err, data) {
assert.ok(!err);
done();
},
);
});
});
group('sliceUploadFile() 完整上传文件', function () {
test('sliceUploadFile() 完整上传文件', function (done) {
var lastPercent;
var filename = '3m.zip';
var fileSize = 1024 * 1024 * 3;
var blob = createFileSync(fileSize);
cos.abortUploadTask(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Level: 'file',
},
function (err, data) {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
expect(data.ETag.length > 0);
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
const success = data && data.headers && parseInt(data.headers['content-length'] || 0) === fileSize;
expect(success);
err ? done(err) : done();
},
);
},
);
},
);
});
test('sliceUploadFile(),pauseTask(),restartTask()', function (done) {
var filename = '10m.zip';
var blob = util.createFile({ size: 1024 * 1024 * 10 });
var paused = false;
var restarted = false;
cos.abortUploadTask(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Level: 'file',
},
function (err, data) {
var TaskId;
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
if (!paused && info.percent > 0.6) {
cos.pauseTask(TaskId);
paused = true;
setTimeout(function () {
restarted = true;
cos.restartTask(TaskId);
}, 1000);
}
if (paused && restarted) {
if (info.percent === 0) return;
expect(info.percent > 0.3);
cos.cancelTask(TaskId);
done();
}
},
},
function (err, data) {
paused = true;
},
);
},
);
});
test('sliceUploadFile(),cancelTask(),restartTask()', function (done) {
var filename = '10m.zip';
var blob = util.createFile({ size: 1024 * 1024 * 3 });
var paused = false;
cos.abortUploadTask(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Level: 'file',
},
function (err, data) {
var TaskId;
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
if (!paused && info.percent > 0.6) {
cos.cancelTask(TaskId);
setTimeout(function () {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
},
function (err, data) {
err ? done(err) : done();
},
);
}, 10);
}
},
},
function (err, data) {},
);
},
);
});
test('sliceUploadFile(),cancelTask()', function (done) {
var filename = '3m.zip';
var alive = false;
var canceled = false;
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: util.createFile({ size: 1024 * 1024 * 3 }),
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
alive = true;
if (!canceled) {
cos.cancelTask(TaskId);
alive = false;
canceled = true;
setTimeout(function () {
done();
}, 1200);
}
},
},
function (err, data) {
alive = true;
},
);
});
});
group('sliceUploadFile() 同时上传2个文件', function () {
var filename = '30m.zip';
var blob = util.createFile({ size: 1024 * 1024 * 30 });
test('sliceUploadFile() 上传文件1', function (done) {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
},
function (err, data) {},
);
});
setTimeout(() => {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
},
function (err, data) {
assert.ok(err);
done();
},
);
}, 2000);
});
group('sliceUploadFile() 续传', function () {
var filename = '30m.zip';
var blob = util.createFile({ size: 1024 * 1024 * 30 });
test('sliceUploadFile() 正常续传', function (done) {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (id) {
setTimeout(() => {
cos.pauseTask(id);
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
},
function (err, data) {
assert.ok(!err);
done();
},
);
}, 2000);
},
},
function (err, data) {},
);
});
test('sliceUploadFile() cancelTask', function (done) {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (id) {
setTimeout(() => {
cos.cancelTask(id);
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
},
function (err, data) {
assert.ok(!err);
done();
},
);
}, 2000);
},
},
function (err, data) {},
);
});
test('sliceUploadFile() 续传时本地文件修改', function (done) {
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (id) {
setTimeout(() => {
cos.pauseTask(id);
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob + '123',
},
function (err, data) {
assert.ok(err);
done();
},
);
}, 2000);
},
},
function (err, data) {},
);
});
});
group('abortUploadTask()', function () {
test('abortUploadTask(),Level=task', function (done) {
var filename = '1m.zip';
cos.multipartInit(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
cos.abortUploadTask(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Level: 'task',
UploadId: data.UploadId,
},
function (err, data) {
var nameExist = false;
data.successList.forEach(function (item) {
if (filename === item.Key) {
nameExist = true;
}
});
assert.ok(data.successList.length >= 1);
assert.ok(nameExist);
err ? done(err) : done();
},
);
},
);
});
test('abortUploadTask(),Level=file', function (done) {
var filename = '1m.zip';
var blob = util.createFile({ size: 1024 * 1024 });
cos.sliceUploadFile({
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
cos.cancelTask(TaskId);
cos.abortUploadTask(
{
Bucket: config.Bucket,
Region: config.Region,
Level: 'file',
Key: filename,
},
function (err, data) {
assert.ok(data.successList.length >= 1);
assert.ok(data.successList[0] && data.successList[0].Key === filename);
err ? done(err) : done();
},
);
},
});
});
test('abortUploadTask(),Level=bucket', function (done) {
var filename = '1m.zip';
var blob = util.createFile({ size: 1024 * 1024 * 10 });
cos.sliceUploadFile({
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: blob,
Headers: {
'x-cos-traffic-limit': 838860800,
},
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
cos.cancelTask(TaskId);
cos.abortUploadTask(
{
Bucket: config.Bucket,
Region: config.Region,
Level: 'bucket',
},
function (err, data) {
var nameExist = false;
data.successList.forEach(function (item) {
if (filename === item.Key) {
nameExist = true;
}
});
assert.ok(data.successList.length >= 1);
assert.ok(nameExist);
err ? done(err) : done();
},
);
},
});
});
});
group('headBucket()', function () {
test('headBucket()', function (done) {
cos.headBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
expect(data.statusCode).toBe(200);
err ? done(err) : done();
},
);
});
test('getBucket()', function (done) {
cos.getBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(data.Name === BucketLongName);
expect(data.Contents).toBeInstanceOf(Array);
err ? done(err) : done();
},
);
});
});
group('putObject()', function () {
var buf = new ArrayBuffer(8);
var arr = new Uint8Array(buf);
[0x89, 0xe8, 0xaf, 0xb4, 0x2e, 0x70, 0x72, 0x70, 0x72].forEach(function (v, i) {
arr[i] = v;
});
test('putObject()', function (done) {
var filename = '1.txt';
var getObjectETag = function (callback) {
setTimeout(function () {
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
callback(data && data.headers && data.headers.etag);
},
);
}, 2000);
};
var content = Date.now().toString();
var lastPercent = 0;
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: util.str2blob(content),
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
assert.ok(data.ETag !== undefined);
getObjectETag(function (ETag) {
assert.ok(data.ETag === ETag);
done();
});
},
);
});
test('putObject(),string', function (done) {
var filename = '1.txt';
var content = '中文_' + Date.now().toString(36);
var lastPercent = 0;
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: content,
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
var ETag = data && data.ETag;
assert.ok(ETag !== undefined);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
assert.ok(data.Body && data.Body === content && (data.headers && data.headers.etag) === ETag);
done();
},
);
},
);
});
test('putObject(),string,empty', function (done) {
var content = '';
var lastPercent = 0;
var Key = '1.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
Body: content,
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
var ETag = data && data.ETag;
assert.ok(ETag !== undefined);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
},
function (err, data) {
assert.ok(data.Body === content && (data.headers && data.headers.etag) === ETag);
done();
},
);
},
);
});
test('putObject(),特殊二进制字符 ArrayBuffer md5', function (done) {
var content = '';
var lastPercent = 0;
var Key = '1.mp4';
var blob = new Blob([buf]);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
Body: blob,
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
var ETag = data && data.ETag;
assert.ok(ETag !== undefined);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
BodyType: 'arraybuffer',
},
function (err, data) {
var arr = new Uint8Array(data.Body);
var isSame = arr.every(function (v, i) {
return v === arr[i];
});
assert.ok(isSame && (data.headers && data.headers.etag) === ETag);
done();
},
);
},
);
});
test('putObject(),特殊二进制字符 Blob md5', function (done) {
var content = '';
var lastPercent = 0;
var Key = '1.mp4';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
Body: buf,
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
var ETag = data && data.ETag;
assert.ok(ETag !== undefined);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
BodyType: 'arraybuffer',
},
function (err, data) {
var arr = new Uint8Array(data.Body);
var isSame = arr.every(function (v, i) {
return v === arr[i];
});
assert.ok(isSame && (data.headers && data.headers.etag) === ETag);
done();
},
);
},
);
});
test('putObject(),特殊二进制字符 中文 string md5', function (done) {
var Key = '1.txt';
var content = '中文';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
Body: content,
},
function (err, data) {
if (err) throw err;
var ETag = data && data.ETag;
assert.ok(ETag !== undefined);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
},
function (err, data) {
var isSame = content === data.Body;
assert.ok(isSame && (data.headers && data.headers.etag) === ETag);
done();
},
);
},
);
});
test('putObject(),特殊二进制字符 unescape string md5', function (done) {
var Key = '1.txt';
var content = unescape(encodeURIComponent('中文'));
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
Body: content,
},
function (err, data) {
if (err) throw err;
var ETag = data && data.ETag;
assert.ok(ETag !== undefined);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
},
function (err, data) {
var isSame = content === data.Body;
assert.ok(isSame && (data.headers && data.headers.etag) === ETag);
done();
},
);
},
);
});
});
group('getObject()', function () {
test('getObject() body', function (done) {
var key = '1.txt';
var content = Date.now().toString();
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
},
function (err, data) {
if (err) throw err;
var objectContent = data.Body.toString();
assert.ok(data.headers['content-length'] === '' + content.length);
assert.ok(objectContent === content);
done();
},
);
},
);
});
test('getObject() bucket not exist', function (done) {
cos.getObject(
{
Bucket: Date.now().toString(36) + config.Bucket,
Region: config.Region,
Key: key,
DataType: 'blob',
},
function (err, data) {
assert.ok(err);
done();
},
);
});
test('getObject() object not exist', function (done) {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Date.now().toString(36) + key,
DataType: 'blob',
},
function (err, data) {
assert.ok(err);
done();
},
);
});
test('getObject() DataType blob', function (done) {
var key = '1.txt';
var content = Date.now().toString();
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
DataType: 'blob',
},
function (err, data) {
if (err) throw err;
expect(data.Body).toBeInstanceOf(Blob);
expect(data.headers['content-length'] === '' + content.length);
done();
},
);
},
);
});
test('getObject() DataType arraybuffer', function (done) {
var key = '1.txt';
var content = Date.now().toString();
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
DataType: 'arraybuffer',
},
function (err, data) {
if (err) throw err;
expect(data.Body).toBeInstanceOf(ArrayBuffer);
expect(data.headers['content-length'] === '' + content.length);
done();
},
);
},
);
});
});
group('Key 特殊字符', function () {
test('Key 特殊字符', function (done) {
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '(!\'*) "#$%&+,-./0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
Body: Date.now().toString(),
},
function (err, data) {
if (err) throw err;
expect(data !== null);
done();
},
);
});
});
group('deleteObject', function () {
test('deleteObject() bucket not exist', function (done) {
cos.deleteObject(
{
Bucket: Date.now().toString(36) + config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
},
function (err, data) {
assert.ok(err);
done();
},
);
});
test('deleteObject() object not exist', function (done) {
cos.deleteObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Date.now().toString(36) + '1.copy.txt',
},
function (err, data) {
assert.ok(err);
done();
},
);
});
});
group('putObjectCopy() 1', function () {
test('putObjectCopy() 1', function (done) {
var content = Date.now().toString(36);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.txt',
Body: content,
},
function (err, data) {
var ETag = data.ETag;
cos.deleteObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
},
function (err, data) {
cos.putObjectCopy(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
CopySource: BucketLongName + '.cos.' + config.Region + '.myqcloud.com/1.txt',
},
function (err, data) {
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
},
function (err, data) {
expect(data.headers && data.headers.etag === ETag);
done();
},
);
},
);
},
);
},
);
});
test('捕获 object 异常', function (done) {
var errFileName = '12345.txt' + Date.now().toString(36);
cos.putObjectCopy(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + errFileName,
},
function (err, data) {
assert.ok(err);
done();
},
);
});
});
group('putObjectCopy()', function () {
var filename = '1.txt';
test('正常复制 object', function (done) {
cos.putObjectCopy(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + filename,
},
function (err, data) {
expect(data.ETag.length > 0);
done();
},
);
});
test('捕获 object 异常', function (done) {
var errFileName = Date.now().toString();
cos.putObjectCopy(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + errFileName,
},
function (err, data) {
expect(err.statusCode === 404);
expect(err.error.Code === 'NoSuchKey');
done();
},
);
});
});
group('sliceCopyFile()', function () {
var filename = 'bigger.zip';
var Key = 'bigger.copy.zip';
test('正常分片复制 object', function (done) {
prepareBigObject(true)
.then(function () {
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data1) {
if (err) throw err;
cos.sliceCopyFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + filename,
CopySliceSize: 5 * 1024 * 1024,
},
function (err, data) {
if (err) throw err;
assert.ok(data.ETag.length > 0);
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
},
function (err, data2) {
if (err) throw err;
['VersionId', 'ETag', 'RequestId'].forEach((key) => {
delete data1[key];
delete data2[key];
});
[
'x-cos-request-id',
'x-cos-version-id',
'x-cos-replication-status',
'last-modified',
'last-modified',
'etag',
'date',
'expires',
].forEach((key) => {
delete data1.headers[key];
delete data2.headers[key];
});
assert.ok(comparePlainObject(data1, data2));
done();
},
);
},
);
},
);
})
.catch(function () {
assert.ok(false);
done();
});
});
test('单片复制 object', function (done) {
setTimeout(function () {
prepareBigObject(true)
.then(function () {
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data1) {
if (err) throw err;
cos.sliceCopyFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + filename,
SliceSize: 10 * 1024 * 1024,
},
function (err, data) {
if (err) throw err;
assert.ok(data.ETag.length > 0);
setTimeout(function () {
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
},
function (err, data2) {
if (err) throw err;
delete data1.VersionId;
delete data2.VersionId;
delete data1.headers['x-cos-request-id'];
delete data2.headers['x-cos-request-id'];
delete data1.headers['x-cos-version-id'];
delete data2.headers['x-cos-version-id'];
delete data1.headers['x-cos-replication-status'];
delete data2.headers['x-cos-replication-status'];
delete data1.headers['last-modified'];
delete data2.headers['last-modified'];
delete data1.headers['date'];
delete data2.headers['date'];
delete data1.ETag;
delete data2.ETag;
delete data1.RequestId;
delete data2.RequestId;
assert.ok(comparePlainObject(data1, data2));
done();
},
);
}, 2000);
},
);
},
);
})
.catch(function () {
done();
});
}, 2000);
});
test('CopySource nor found', function (done) {
cos.sliceCopyFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
CopySource: config.Bucket + '.cos.' +