@nocobase/plugin-file-manager
Version:
Provides files storage services with files collection template and attachment field.
1,877 lines (1,838 loc) • 169 kB
JavaScript
var fs = require('fs');
var path = require('path');
var COS = require('../index');
var request = require('request');
var util = require('../demo/util');
var config = require('../demo/config');
var Stream = require('stream');
// 先删除测试文件zip
const dir = path.resolve(__dirname);
fs.readdir(dir, (error, data) => {
if (error) {
console.log('readdir error', error);
} else {
data.forEach((filename) => {
if (filename.endsWith('.zip')) {
fs.rmSync(path.resolve(__dirname, filename));
}
});
}
});
var Writable = Stream.Writable;
var dataURItoUploadBody = function (dataURI) {
return Buffer.from(dataURI.split(',')[1], 'base64');
};
var createFileSync = function (filePath, size) {
if (!fs.existsSync(filePath) || fs.statSync(filePath).size !== size) {
fs.writeFileSync(filePath, Buffer.from(Array(size).fill(0)));
}
return filePath;
};
function camSafeUrlEncode(str) {
return encodeURIComponent(str)
.replace(/!/g, '%21')
.replace(/'/g, '%27')
.replace(/\(/g, '%28')
.replace(/\)/g, '%29')
.replace(/\*/g, '%2A');
}
var assert = require('assert');
assert.ok = assert;
var test = function (name, fn) {
it(name, function (done) {
fn(done, assert);
});
};
var group = function (name, fn) {
describe(name, function () {
this.timeout(120000);
fn.apply(this, arguments);
});
};
var proxy = '';
if (!config.SecretId || !config.SecretKey || !config.Bucket || !config.Region || !config.Uin) {
console.log('Please check for complete configuration information in demo/config.js');
console.log('请检查demo/config.js是否有完整的配置信息');
return;
}
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Proxy: proxy,
// 可选参数
FileParallelLimit: 6, // 控制文件上传并发数
ChunkParallelLimit: 3, // 控制单个文件下分片上传并发数
ChunkSize: 1024 * 1024, // 控制分片大小,单位 B
ProgressInterval: 1, // 控制 onProgress 回调的间隔
ChunkRetryTimes: 3, // 控制文件切片后单片上传失败后重试次数
UploadCheckContentMd5: true, // 上传过程计算 Content-MD5
ServiceDomain: 'service.cos.myqcloud.com/',
});
var AppId;
var Bucket = config.Bucket;
var BucketShortName = Bucket;
var BucketLongName = Bucket + '-' + AppId;
var TaskId;
var match = config.Bucket.match(/^(.+)-(\d+)$/);
if (match) {
BucketLongName = config.Bucket;
BucketShortName = match[1];
AppId = match[2];
}
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() {
return new Promise(function (resolve, reject) {
// 创建测试文件
var filename = 'bigger.zip';
var content = Buffer.from(Array(1024 * 1024 * 10).fill(0));
var put = function () {
// 调用方法
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: content,
ContentLength: content.length,
},
function (err, data) {
err ? reject(err) : resolve();
}
);
};
put();
});
}
function prepareBucket() {
return new Promise(function (resolve, reject) {
cos.putBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
resolve();
}
);
});
}
function prepareObject(key = '1.txt') {
return new Promise(function (resolve, reject) {
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: '123456',
},
function (err, data) {
err ? reject(err) : resolve(data);
}
);
});
}
function deleteObjectBefore(Key) {
return new Promise(function (resolve, reject) {
cos.deleteObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key,
},
function (err, data) {
err ? reject(err) : resolve(data);
}
);
});
}
group('init cos', function () {
const putFile = function (cosIns, done, assert, canSuccess = true) {
var key = '1.txt';
var content = Date.now().toString();
cosIns.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
assert.ok(canSuccess ? !err : err);
done();
}
);
};
test('使用AppId', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
AppId: 12500000000,
});
assert.ok(initCos.options.AppId);
done();
});
test('使用了小写ak sk', function (done, assert) {
var initCos = new COS({
secretId: config.SecretId,
secretKey: config.SecretKey,
});
putFile(initCos, done, assert, true);
});
test('SecretId格式错误', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId + ' ',
SecretKey: config.SecretKey,
});
var key = '1.txt';
var content = Date.now().toString();
putFile(initCos, done, assert, false);
});
test('SecretKey格式错误', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey + ' ',
});
putFile(initCos, done, assert, false);
});
test('StrictSsl=false', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
StrictSsl: false,
});
putFile(initCos, done, assert, true);
});
test('Tunnel=false', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Tunnel: false,
});
putFile(initCos, done, assert, true);
});
test('Timeout=6000', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
Timeout: 6000,
});
putFile(initCos, done, assert, true);
});
test('ForcePathStyle', function (done, assert) {
var initCos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
ForcePathStyle: true,
});
putFile(initCos, done, assert, true);
});
test('模拟sms init', function (done, assert) {
var Credentials = {
secretId: config.SecretId,
secretKey: config.SecretKey,
};
var initCos = new COS({ Credentials });
setTimeout(() => {
Credentials.secretId = '123456';
Credentials.secretKey = 'abcdefg';
}, 1000);
putFile(initCos, done, assert, true);
});
test('getAuthorization error tmpSecretId', function (done, assert) {
var initCos = new COS({
getAuthorization: function (options, callback) {
callback({
tmpSecretId: config.SecretId,
TmpSecretKey: config.SecretKey,
});
},
});
putFile(initCos, done, assert, false);
});
test('getAuthorization error tmpSecretKey', function (done, assert) {
var initCos = new COS({
getAuthorization: function (options, callback) {
callback({
TmpSecretId: config.SecretId,
tmpSecretKey: config.SecretKey,
});
},
});
putFile(initCos, done, assert, false);
});
test('getAuthorization error', function (done, assert) {
var initCos = new COS({
getAuthorization: function (options, callback) {
callback({
TmpSecretId: config.SecretId,
TmpSecretKey: config.SecretKey,
});
},
});
putFile(initCos, done, assert, false);
});
test('getAuthorization', function (done, assert) {
var initCos = new COS({
getAuthorization: function (options, callback) {
var AuthData = cos.getAuth({
Method: 'put',
Key: '1.txt',
});
callback({
Authorization: AuthData,
});
},
});
putFile(initCos, done, assert);
});
});
group('getService()', function () {
test('getService 老用法', function (done, assert) {
prepareBucket().then(function () {
cos.getService(function (err, data) {
assert.ok(!err);
done();
});
});
});
test('getService 传Region', function (done, assert) {
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
});
prepareBucket()
.then(function () {
cos.getService(
{
Region: config.Region,
},
function (err, data) {
var hasBucket = false;
data.Buckets &&
data.Buckets.forEach(function (item) {
if (item.Name === BucketLongName && (item.Location === config.Region || !item.Location)) {
hasBucket = true;
}
});
assert.ok(hasBucket);
done();
}
);
})
.catch(function () {});
});
test('getService 不传Region和Domain', function (done, assert) {
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
});
prepareBucket()
.then(function () {
cos.getService({}, function (err, data) {
var hasBucket = false;
data.Buckets &&
data.Buckets.forEach(function (item) {
if (item.Name === BucketLongName && (item.Location === config.Region || !item.Location)) {
hasBucket = true;
}
});
assert.ok(hasBucket);
done();
});
})
.catch(function () {});
});
test('能正常列出 Bucket', function (done, assert) {
prepareBucket()
.then(function () {
cos.getService(
{
Region: config.Region,
},
function (err, data) {
var hasBucket = false;
data.Buckets &&
data.Buckets.forEach(function (item) {
if (item.Name === BucketLongName && (item.Location === config.Region || !item.Location)) {
hasBucket = true;
}
});
assert.ok(hasBucket);
done();
}
);
})
.catch(function () {});
});
});
group('putBucket()', function () {
var NewBucket = 'test' + Date.now().toString(36) + '-' + AppId;
test('正常创建 bucket', function (done, assert) {
cos.putBucket(
{
Bucket: NewBucket,
Region: config.Region,
},
function (err, data) {
var location1 = NewBucket + '.cos.' + config.Region + '.myqcloud.com';
var location2 = NewBucket + '.cos.' + config.Region + '.myqcloud.com/';
assert.ok(location1 === data.Location || location2 === data.Location);
cos.headBucket(
{
Bucket: NewBucket,
Region: config.Region,
},
function (err, data) {
assert.ok(data);
cos.deleteBucket(
{
Bucket: NewBucket,
Region: config.Region,
},
function (err, data) {
done();
}
);
}
);
}
);
});
});
group('getAuth();getV4Auth()', function () {
test('getAuth()', function (done, assert) {
var content = Date.now().toString();
var key = '1.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
var AuthData = cos.getAuth({
Method: 'get',
Key: key,
});
if (typeof AuthData === 'string') {
AuthData = { Authorization: AuthData };
}
var link =
'http://' +
config.Bucket +
'.cos.' +
config.Region +
'.myqcloud.com' +
'/' +
camSafeUrlEncode(key).replace(/%2F/g, '/') +
'?' +
AuthData.Authorization +
(AuthData.XCosSecurityToken ? '&x-cos-security-token=' + AuthData.XCosSecurityToken : '');
request(
{
url: link,
proxy: proxy,
},
function (err, response, body) {
assert.ok(response.statusCode === 200);
assert.ok(body === content);
done();
}
);
}
);
});
test('getV4Auth()', function (done, assert) {
var content = Date.now().toString();
var key = '1.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
var sign = cos.getV4Auth({
Bucket: config.Bucket,
Key: key,
});
var link =
'http://' +
config.Bucket +
'.cos.' +
config.Region +
'.myqcloud.com' +
'/' +
camSafeUrlEncode(key).replace(/%2F/g, '/') +
'?sign=' +
encodeURIComponent(sign);
request(
{
url: link,
proxy: proxy,
},
function (err, response, body) {
assert.ok(response.statusCode === 200);
assert.ok(body === content);
done();
}
);
}
);
});
});
group('putObject() 兼容老参数AppId', function () {
test('putObject()', function (done, assert) {
const sp = config.Bucket.split('-');
const len = sp.length;
const appId = sp[len - 1];
sp.pop();
const bucketShortName = sp.join('-');
cos.putObject(
{
Bucket: bucketShortName,
Region: config.Region,
AppId: appId,
Key: '12345.txt',
Body: '12345',
Headers: {
'x-cos-test': 1,
},
},
function (err, data) {
assert.ok(!err);
done();
}
);
});
});
group('getObjectUrl()', function () {
test('getObjectUrl()', function (done, assert) {
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,
},
function (err, data) {
request(
{
url: data.Url,
proxy: proxy,
},
function (err, response, body) {
assert.ok(!err);
done();
}
);
}
);
}
);
});
test('getObjectUrl() Query', function (done, assert) {
var key = '1.txt';
var content = '12345';
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: true,
},
function (err, data) {
request(
{
url: data.Url,
proxy: proxy,
},
function (err, response, body) {
assert.ok(!err, '文件获取出错');
assert.ok(response.statusCode === 200, '获取文件 200');
assert.ok(body.toString() === content, '通过获取签名能正常获取文件');
done();
}
);
}
);
}
);
});
test('getObjectUrl() QueryString', function (done, assert) {
var key = '1.txt';
cos.getObjectUrl(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
QueryString: 'a=1',
Sign: true,
},
function (err, data) {
request(
{
url: data.Url,
proxy: proxy,
},
function (err, response, body) {
assert.ok(!err, '文件获取出错');
assert.ok(response.statusCode === 200, '获取文件 200');
done();
}
);
}
);
});
test('getObjectUrl() sign=false', function (done, assert) {
var key = '1.txt';
cos.getObjectUrl(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
QueryString: 'a=1',
Sign: false,
},
function (err, data) {
request(
{
url: data.Url,
proxy: proxy,
},
function (err, response, body) {
assert.ok(response.statusCode === 403, '获取文件 403');
done();
}
);
}
);
});
});
group('auth check', function () {
test('auth check', function (done, assert) {
cos.getBucket(
{
Bucket: config.Bucket,
Region: config.Region,
Prefix: 'aksjhdlash sajlhj!@#$%^&*()_+=-[]{}\';:"/.<>?.,??sadasd#/.,/~`',
Headers: {
'x-cos-test': 'aksjhdlash sajlhj!@#$%^&*()_+=-[]{}\';:"/.<>?.,??sadasd#/.,/~`',
},
},
function (err, data) {
assert.ok(!err);
done();
}
);
});
});
group('getBucket(),listObjectVersions', function () {
test('正常获取 bucket 里的文件列表', function (done, assert) {
prepareBucket()
.then(function () {
cos.getBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(data.Name === BucketLongName);
assert.ok(data.Contents.constructor, Array);
done();
}
);
})
.catch(function () {
assert.ok(false);
done();
});
});
test('正常获取 bucket 里的文件版本列表', function (done, assert) {
prepareBucket()
.then(function () {
cos.listObjectVersions(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(data.Name === BucketLongName);
assert.ok(data.Versions.constructor === Array);
done();
}
);
})
.catch(function () {
assert.ok(false);
done();
});
});
});
group('putObject(),cancelTask()', function () {
test('putObject(),cancelTask()', function (done, assert) {
var filename = '10m.zip';
var alive = false;
var canceled = false;
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: Buffer.from(Array(1024 * 1024 * 10).fill(0)),
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
alive = true;
if (!canceled) {
cos.cancelTask(TaskId);
alive = false;
canceled = true;
setTimeout(function () {
assert.ok(!alive, '取消上传已经生效');
done();
}, 1200);
}
},
},
function (err, data) {
alive = true;
}
);
});
test('putObject(),update-list()', function (done, assert) {
var filename = '10m.zip';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: Buffer.from(Array(1024 * 1024 * 10).fill(0)),
},
function (err, data) {
assert(!err);
done();
}
);
cos.on('task-list-update', function () {});
});
});
group('task 队列', function () {
test('putObject() 批量上传', function (done, assert) {
var upload = function () {
var filename = '10m.zip';
var taskId;
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: Buffer.from(Array(1024 * 1024 * 1).fill(0)),
TaskReady: function (id) {
taskId = id;
},
},
function (err, data) {}
);
};
for (var i = 0; i < 1200; i++) {
upload();
}
var taskList = cos.getTaskList();
const isUploading = cos.isUploadRunning();
assert(isUploading);
done();
});
});
group('sliceUploadFile() 完整上传文件', function () {
test('sliceUploadFile() 完整上传文件', function (done, assert) {
var lastPercent;
var filename = '3m.zip';
var fileSize = 1024 * 1024 * 3;
var filePath = createFileSync(path.resolve(__dirname, filename), 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,
FilePath: filePath,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
assert.ok(data.ETag.length > 0);
fs.unlinkSync(filePath);
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
assert.ok(data && data.headers && data.headers.etag && data.headers.etag.length > 0, '文件已上传成功');
assert.ok(
data && data.headers && parseInt(data.headers['content-length'] || 0) === fileSize,
'文件大小一致'
);
done();
}
);
}
);
}
);
});
test('sliceUploadFile(),pauseTask(),restartTask()', function (done, assert) {
var cos = new COS({
SecretId: config.SecretId,
SecretKey: config.SecretKey,
});
var filename = '10m.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 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,
FilePath: filePath,
onTaskReady: function (taskId) {
TaskId = taskId;
cos.on('list-update', (info) => {
const fileTask = info.list.find((item) => item.id === taskId);
if (fileTask && paused && restarted) {
if (fileTask.percent === 0) return;
assert.ok(fileTask.percent > 0.3, '暂停和重试成功');
cos.cancelTask(TaskId);
fs.unlinkSync(filePath);
done();
}
});
},
onProgress: function (info) {
if (!paused && info.percent > 0.6) {
cos.pauseTask(TaskId);
paused = true;
setTimeout(function () {
restarted = true;
cos.restartTask(TaskId);
}, 1000);
}
},
},
function (err, data) {
paused = true;
}
);
}
);
});
test('sliceUploadFile(),cancelTask(),restartTask()', function (done, assert) {
var filename = '10m.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024 * 10);
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,
FilePath: filePath,
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,
FilePath: filePath,
},
function (err, data) {
assert.ok(!err);
fs.unlinkSync(filePath);
done();
}
);
}, 10);
}
},
},
function (err, data) {}
);
}
);
});
test('sliceUploadFile(),cancelTask()', function (done, assert) {
var filename = '3m.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024 * 3);
var alive = false;
var canceled = false;
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
alive = true;
if (!canceled) {
cos.cancelTask(TaskId);
alive = false;
canceled = true;
fs.unlinkSync(filePath);
setTimeout(function () {
assert.ok(!alive, '取消上传已经生效');
done();
}, 1200);
}
},
},
function (err, data) {
alive = true;
}
);
});
test('sliceUploadFile() fileSize = 0', function (done, assert) {
var filename = '0b.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 0);
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
Headers: {
'x-cos-test': 'test',
'x-cos-meta-test': 'meta',
'x-cos-traffic-limit': 819200,
},
},
function (err, data) {
assert(!err);
done();
}
);
});
test('sliceUploadFile() 上传过程中删除本地文件', function (done, assert) {
var filename = '30mb.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024 * 30);
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
},
function (err, data) {
assert(err);
done();
}
);
setTimeout(() => {
fs.rmSync(filePath);
}, 1000);
});
test('sliceUploadFile() 上传过程中本地文件修改', function (done, assert) {
var filename = '30mb.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024 * 30);
var taskId;
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
onTaskReady: function (id) {
taskId = id;
},
},
function (err, data) {
// assert(err);
// done();
}
);
setTimeout(() => {
// 先暂停任务
cos.pauseTask(taskId);
// 重新上传
cos.sliceUploadFile(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
},
function (err, data) {
console.log(err ? '失败' : '成功');
assert.ok(1);
done();
}
);
// 1秒后修改文件内容
setTimeout(() => {
const fd = fs.openSync(filePath, 'r+');
fs.writeSync(fd, 'test', 10240, 'utf8');
console.log('文件被修改');
}, 1000);
}, 1000);
});
});
group('abortUploadTask()', function () {
test('abortUploadTask(),Level=task', function (done, assert) {
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, '成功取消单个分片任务');
done();
}
);
}
);
});
test('abortUploadTask(),Level=file', function (done, assert) {
var filename = '1m.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024);
cos.sliceUploadFile({
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
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, '成功舍弃单个文件的所有分片任务');
done();
}
);
},
});
});
test('abortUploadTask(),Level=bucket', function (done, assert) {
var filename = '1m.zip';
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024);
cos.sliceUploadFile({
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
FilePath: filePath,
onTaskReady: function (taskId) {
TaskId = taskId;
},
onProgress: function (info) {
cos.cancelTask(TaskId);
fs.unlinkSync(filePath);
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, '成功舍弃Bucket下所有分片任务');
assert.ok(nameExist, '成功舍弃Bucket下所有分片任务');
done();
}
);
},
});
});
});
group('headBucket()', function () {
test('headBucket()', function (done, assert) {
cos.headBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(data, '正常获取 head bucket');
done();
}
);
});
test('headBucket() bucket not exist', function (done, assert) {
cos.headBucket(
{
Bucket: Date.now().toString(36) + config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(err, 'bucket 不存在');
done();
}
);
});
test('deleteBucket()', function (done, assert) {
cos.deleteBucket(
{
Bucket: Date.now().toString(36) + config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(err, 'deleteBucket 不存在');
done();
}
);
});
test('getBucket()', function (done, assert) {
cos.getBucket(
{
Bucket: config.Bucket,
Region: config.Region,
},
function (err, data) {
assert.ok(data.Name === BucketLongName, '能列出 bucket');
assert.ok(data.Contents.constructor === Array, '正常获取 bucket 里的文件列表');
done();
}
);
});
});
group('putObject()', function () {
var filename = `${Date.now().toString()}_1.txt`;
var filePath = path.resolve(__dirname, filename);
var getObjectContent = function (callback) {
var objectContent = Buffer.from([]);
var outputStream = new Writable({
write: function (chunk, encoding, callback) {
objectContent = Buffer.concat([objectContent, chunk]);
callback();
},
});
setTimeout(function () {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
onProgress: function (info) {},
Output: outputStream,
},
function (err, data) {
var content = objectContent.toString();
callback(content);
}
);
}, 2000);
};
test('fs.createReadStream 创建 object', function (done, assert) {
var content = Date.now().toString();
fs.writeFileSync(filePath, content);
var lastPercent = 0;
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: fs.createReadStream(filePath),
ContentLength: fs.statSync(filePath).size,
onTaskReady(id) {
// 暂停任务
// cos.pauseTask(id);
},
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
assert.ok(data.ETag.length > 0);
fs.unlinkSync(filePath);
getObjectContent(function (objectContent) {
assert.ok(objectContent === content);
done();
});
}
);
});
test('fs.readFileSync 创建 object', function (done, assert) {
var content = Date.now().toString();
fs.writeFileSync(filePath, content);
var lastPercent = 0;
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: fs.readFileSync(filePath),
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
assert.ok(data.ETag.length > 0);
fs.unlinkSync(filePath);
getObjectContent(function (objectContent) {
assert.ok(objectContent === content);
done();
});
}
);
});
test('捕获输入流异常', function (done, assert) {
var filename = 'big.zip';
var filePath = path.resolve(__dirname, filename);
var put = function () {
var Body = fs.createReadStream(filePath);
setTimeout(function () {
Body.emit('error', new Error('some error'));
}, 1000);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: Body,
ContentLength: fs.statSync(filePath).size,
},
function (err, data) {
fs.unlinkSync(filePath);
done();
}
);
};
if (fs.existsSync(filePath)) {
put();
} else {
util.createFile(filePath, 5 << 20, put);
}
});
test('putObject(),buffer', function (done, assert) {
var content = Buffer.from('中文_' + Date.now());
const filename = Date.now() + '1.txt';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
Body: content,
},
function (err, data) {
var ETag = data.ETag;
assert.ok(!err && ETag);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
console.log('data.Body', data.Body.toString());
console.log('content.toString()', content.toString());
console.log('data.headers', data.headers);
assert.ok(
data.Body && data.Body.toString() === content.toString() && (data.headers && data.headers.etag) === ETag
);
done();
}
);
}
);
});
test('putObject(),buffer,empty', function (done, assert) {
var content = Buffer.from('');
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.txt',
Body: content,
},
function (err, data) {
var ETag = data.ETag;
assert.ok(!err && ETag);
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
assert.ok(
data.Body && data.Body.toString() === content.toString() && (data.headers && data.headers.etag) === ETag
);
done();
}
);
}
);
});
test('putObject()', function (done, assert) {
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: content,
onProgress: function (info) {
lastPercent = info.percent;
},
},
function (err, data) {
if (err) throw err;
assert.ok(data && data.ETag, 'putObject 有返回 ETag');
getObjectETag(function (ETag) {
assert.ok(data.ETag === ETag, 'Blob 创建 object');
done();
});
}
);
});
test('putObject(),string', function (done, assert) {
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, 'putObject 有返回 ETag');
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: filename,
},
function (err, data) {
assert.ok(
data.Body && data.Body.toString() === content.toString() && (data.headers && data.headers.etag) === ETag
);
done();
}
);
}
);
});
test('putObject(),string,empty', function (done, assert) {
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, 'putObject 有返回 ETag');
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: Key,
},
function (err, data) {
assert.ok(data.Body && data.Body.toString() === content && (data.headers && data.headers.etag) === ETag);
done();
}
);
}
);
});
});
group('getObject(),getObjectStream()', function () {
test('getObject() body', function (done, assert) {
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() stream', function (done, assert) {
var key = '1.txt';
var objectContent = Buffer.from([]);
var outputStream = new Writable({
write: function (chunk, encoding, callback) {
objectContent = Buffer.concat([objectContent, chunk]);
callback();
},
});
var content = Date.now().toString(36);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: Buffer.from(content),
},
function (err, data) {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Output: outputStream,
},
function (err, data) {
if (err) throw err;
objectContent = objectContent.toString();
assert.ok(data.headers['content-length'] === '' + content.length);
assert.ok(objectContent === content);
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
},
function (err, data) {
assert.ok(!err);
done();
}
);
}
);
}
);
});
test('getObject() stream2', function (done, assert) {
var key = '1.txt';
var objectContent = Buffer.from([]);
var outputStream = new Writable({
write: function (chunk, encoding, callback) {
objectContent = Buffer.concat([objectContent, chunk]);
callback();
},
});
var content = Date.now().toString(36);
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: Buffer.from(content),
},
function (err, data) {
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Output: './1.txt',
},
function (err, data) {
if (err) throw err;
objectContent = objectContent.toString();
assert.ok(data.headers['content-length'] === '' + content.length);
assert.ok(objectContent !== content);
cos.headObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
},
function (err, data) {
assert.ok(!err);
done();
}
);
}
);
}
);
});
test('getObjectStream', function (done, assert) {
var content = Date.now().toString();
var key = '1.json';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
var bufList = [];
var writeStream = new Writable({
write: function (chunk, encoding, callback) {
bufList.push(chunk);
callback();
},
});
cos
.getObjectStream(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
},
function (err, data) {
assert.ok(Buffer.concat(bufList).toString() === content);
done();
}
)
.pipe(writeStream);
}
);
});
test('getObject Output', function (done, assert) {
var content = Date.now().toString();
var key = '1.json';
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Body: content,
},
function (err, data) {
var bufList = [];
var writeStream = new Writable({
write: function (chunk, encoding, callback) {
bufList.push(chunk);
callback();
},
});
cos.getObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: key,
Output: writeStream,
},
function (err, data) {
assert.ok(Buffer.concat(bufList).toString() === content);
done();
}
);
}
);
});
});
group('deleteObject() 404', function () {
test('deleteObject() 404', function (done, assert) {
cos.deleteObject(
{
Bucket: Date.now().toString(36) + config.Bucket,
Region: config.Region,
Key: '123abc' + Date.now().toString(36),
},
function (err, data) {
assert.ok(data.statusCode === 404);
done();
}
);
});
});
group('Key 特殊字符', function () {
test('Key 特殊字符', function (done, assert) {
cos.putObject(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '(!\'*) "#$%&+,-./0123456789:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~',
Body: Date.now().toString(),
},
function (err, data) {
assert.ok(data, 'putObject 特殊字符的 Key 能通过');
done();
}
);
});
});
group('putObjectCopy() 1', function () {
test('putObjectCopy() 1', function (done, assert) {
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: config.Bucket + '.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) {
assert.ok(data.headers && data.headers.etag === ETag, '成功复制文件');
done();
}
);
}
);
}
);
}
);
});
});
group('putObjectCopy()', function () {
var filename = '1.txt';
test('正常复制 object', function (done, assert) {
prepareObject(filename).then(() => {
cos.putObjectCopy(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + filename,
},
function (err, data) {
assert.ok(!err);
assert.ok(data.ETag.length > 0);
done();
}
);
});
});
test('捕获 object 异常', function (done, assert) {
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();
}
);
});
test('putObjectCopy error source', function (done, assert) {
var errFileName = '12345.txt';
cos.putObjectCopy(
{
Bucket: config.Bucket,
Region: config.Region,
Key: '1.copy.txt',
CopySource: 'www.qq.com' + errFileName,
},
function (err, data) {
assert.ok(err);
done();
}
);
});
});
group('sliceCopyFile()', function () {
var filename = 'bigger.zip';
var Key = 'bigger.copy.zip';
test('正常分片复制 object', function (done, assert) {
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,
Headers: {
'x-cos-metadata-directive': 'Replaced',
},
},
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;
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'];
del