UNPKG

cos-js-sdk-v5

Version:

JavaScript SDK for [腾讯云对象存储](https://cloud.tencent.com/product/cos)

1,557 lines (1,516 loc) 197 kB
/** * @jest-environment jsdom */ import { describe, expect, jest, test } from '@jest/globals'; import COS from '../index.js'; import Beacon from '../demo/common/beacon.min'; import ClsClient from '../demo/common/cls.min'; // 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, StsUrl: process.env.jssdkStsUrl, }; // 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); var file = new File([blob], `file-${Date.now()}`, { type: options.type, lastModified: Date.now(), lastModifiedDate: new Date(), }); file.lastModifiedDate = new Date(); return file; }, 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, }); console.log('config.StsUrl========', config.StsUrl); function getSts(options) { return new Promise((resolve, reject) => { var url = `${config.StsUrl}/sts`; // 如果是 npm run sts.js 起的 nodejs server,使用这个 var xhr = new XMLHttpRequest(); xhr.open('get', url, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = function (e) { var data,credentials; try { data = JSON.parse(e.target.responseText); credentials = data.credentials; } catch (e) {} if (!data || !credentials) { console.error('credentials invalid:\n' + JSON.stringify(data, null, 2)); reject(); } resolve({ TmpSecretId: credentials.tmpSecretId, TmpSecretKey: credentials.tmpSecretKey, SecurityToken: credentials.sessionToken, StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000000 }); }; xhr.send(JSON.stringify(options?.Scope)); }); } // todo 只能这么提前获取 const sts = {}; getSts().then(data => { Object.assign(sts, data); }); // 使用临时密钥 var tempCOS = new COS({ getAuthorization: async function (options, callback) { try { const res = await getSts(options); callback({ TmpSecretId: res.TmpSecretId, TmpSecretKey: res.TmpSecretKey, SecurityToken: res.SecurityToken, StartTime: res.StartTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: res.ExpiredTime, // 时间戳,单位秒,如:1580000000 ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用 }); } catch (e) { console.error('get sts error'); } }, }); // 使用临时密钥(老版本使用的XCosSecurityToken) var oldTempCOS = new COS({ // UseAccelerate: true, getAuthorization: async function (options, callback) { try { const res = await getSts(options); callback({ TmpSecretId: res.TmpSecretId, TmpSecretKey: res.TmpSecretKey, XCosSecurityToken: res.SecurityToken, StartTime: res.StartTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: res.ExpiredTime, // 时间戳,单位秒,如:1580000000 ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用 }); } catch (e) { console.error('get sts error'); } }, }); // 后端下发 putObject 前面 Key 为 1.txt var getSignCOS = new COS({ // UseAccelerate: true, getAuthorization: function (options, callback) { var url = `${config.StsUrl}/uploadSign`; // 如果是 npm run sts.js 起的 nodejs server,使用这个 var xhr = new XMLHttpRequest(); xhr.open('get', url, true); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = function (e) { try { var data = JSON.parse(e.target.responseText); } catch (e) {} if (!data) { return console.error('credentials invalid:\n' + JSON.stringify(data, null, 2)); } callback({ Authorization: data?.signMap?.PutObject, }); }; xhr.send(); }, }); var getStsCOS = new COS({ // UseAccelerate: true, getSTS: async function (options, callback) { try { const res = await getSts(options); callback({ TmpSecretId: res.TmpSecretId, TmpSecretKey: res.TmpSecretKey, XCosSecurityToken: res.SecurityToken, StartTime: res.StartTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: res.ExpiredTime, // 时间戳,单位秒,如:1580000000 ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用 }); } catch (e) { console.error('get sts error'); } }, }); // 临时密钥允许的路径 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(1 * 60 * 1000); fn.apply(this, arguments); }); }; var assert = { ok: function (val) { expect(Boolean(val)).toBeTruthy(); }, }; var base64Url = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAAAXNSR0IArs4c6QAAGz5JREFUeF7tnX+QnVV5x7/PvZvsboIkmyAKRSJprTrWgikUGkstHaVqp2K1bHU6kESptVWxdSq7oNaMCmR1ptZNADsKJCkztkE7aK1FZYpCEnXQQGLW4K8ovwQk2c0PsnuT7N7TeTdZZrPZ3fs+73vO+55z3u/+u895znO+z5Pv3txz388V8IcKUIHKKiCVPTkPTgWoAGgAHAIqUGEFaAAVbj6PTgVoAJwBKlBhBWgAFW4+j04FaAC+zsAd5iyMYjkM2tHEDrxTtvtaKusKVwEagI+922gulCY+DowbQBsEPzKCG7BCvuhjuawpXAVoAL717jazXGr4KoCuqaUZgyuxSv7dt5JZT7gK0AB86t3Gp+ZL8wUPAHj5DGUNGcF5WCGP+lQ2awlXARqAR72rrTcfN8CHZytJgNubK+UdHpXNUgJWgAbgS/M2mN8Wg20A5rcoadQILsEK2exL6awjXAVoAJ70rrbBbDIGl6cs534zD5egW8ZSxjOMCkyrAA3Ah8G43bwOddwtTdTSlsM3BNMqxbgW/6WkQKUqsMnMlWFsAXC+qg7BI6YT56Jb9qvWMZgKTFKArwDKHocN5m/F4LNZyhDgE82V8pEsa7mGCiQK0ADKnION5nRp4iEAZ2Qs45ARLMMK+UnG9VxWcQVoACUOQG29+ZQB/ilPCSK4s7lCuvPk4NrqKkADKKv3t5pzpYbvQdCetwRjcClWyTfz5uH66ilAAyip57LB/A8M3mhp+wfNPFyEbjliKR/TVEQBGkAZjd5gLhODu2xubYD3YqXcZDMnc8WvAA2g6B6vNvPkxfj+LJ/3z1rRk6aG83Cl/DprAq6rngI0gKJ7vt5cI0Cfi20F6G+ulPe7yM2ccSpAAyiyr3eYs2QUO6Z71NdKGQaHTRMXEh5iRc1KJKEBFNjm2npzmwFWOd7ym2alXOp4D6aPRAEaQFGN3GguRBP3CTDX9ZZGcDnpQa5VjiM/DaCIPm4ydRnGvQAuLmI7ALtM7ekLcOULDxW0H7cJVAEaQBGNu91cIYKNRWw1sYcBerBSPlnkntwrPAVoAK57tskskOFx0MdS11tNyU98WMGCh7gdDcBx19JgvlyVQHyYK2XjyUsDcNnL9JgvV1UQH+ZK2Ujy0gAcNlKJ+XJVCfFhrpSNIC8NwFUTM2C+XJVCfJgrZcPPSwNw0cOsmC8XtSQ5iQ9zpWzweWkALlqYA/PlopxjHkB8mCttQ85LA7DdvfyYL9sVTeQjPsyVsgHnpQFYbl5tvfmMAa62nNZKOuLDrMgYVRIagM12WsR82Sxrci7iw1wpG2ZeGoDFvlnGfFms7IRUxIe5UjbAvDQAW01zgPmyVdrUPMSHuVI2vLw0ABs9c4f5slHddDmID3OlbGB5aQA2GuYQ82WjvOlyEB/mStmw8tIA8vbLNeYrb30zrSc+zJWyQeWlAeRsV0GYr5xVzric+DBXygaSlwaQp1EFYr7ylDnbWuLDXCkbRl4aQNY+FY/5ylppq3XEh7VSKOLf0wCyNrcEzFfWUlutIz6slULx/p4GkKW35WG+slSbZg3xYWlUijCGBpChqWVivjKUm2oJ8WGpZIouiAagbWn5mC9txWnjR00Tr8E7ZGvaBYwLXwEagLKHnmC+lFWnDic+LLVUcQTSADR99AjzpSlbE0t8mEat8GNpAGl76BvmK23d2jjiw7SKBR1PA0jbPg8xX2lL18YRH6ZVLNx4GkCa3vmL+UpTfZYY4sOyqBbgGhpAiqb5jPlKUX6mEOLDMskW3CIaQKuWBYD5anWErL8nPiyrcuGsowG06FUgmC9XE/d9Mw+vRrcccbUB85arAA1gNv0Dwny5GiPiw1wp60deGsBMfdj41HxpvuABAC/3o1WlVUF8WGnSu9+YBjCTxgFivlyNC/FhrpQtPy8NYLoebDBni8FDALrKb5EHFRAf5kET3JRAA5hG18AxX64m5WtmhfyZm+TMWpYCNICpyt9mlksN3wbQVlZTfN3XGLwVq+S/fK2PdekVoAFM1iwezJd+EtKtID4snU7BRNEAJrcqIsyXqwkkPsyVsuXkpQFM6B4f5svVRBEf5krZEvLSAI6LHiPmy9U8ER/mStni89IAEs3jxXy5mijiw1wpW3BeGgCAyDFfrkaK+DBXyhaYlwZQAcyXq3kiPsyVssXlrbYBVAXz5W6edpt5WIZu2e9uC2Z2qUC1DWC9eY8A61wKHHtu4sPC7nB1DaB6mC9Xk0p8mCtlC8hbWQOoIubL1TwRH+ZKWfd5q2kAFcZ8uRop4sNcKes2byUNoOKYL1cTRXyYK2Ud5q2eAdxu3iKCLznUtLKpjeDdWCH/VlkBAjx4tQyAmC/XI0p8mGuFLeevlgEQ82V5fE5OR3yYc4mtblAdAyDmy+rgzJiM+LBidLa0S2UMgJgvSxOTJo2A+LA0OnkQUw0DIOar8FEzgjdjhXy58I25oUqB+A2AmC/VQFgMJj7MopiuUsVvAMR8uZqdlnmJD2spUekBcRtAgvkawXYYLCld6WoWQHyY532P2wDu23Wd/Oxl16PmeRdiLU8A8zP8H/ZhRwrM+qhlGXzpelF1HALwMBZjE1bLcFot4zWAzdtfCql/F79aUpODp5xKE0g7Epbikn/8+3EAPwa1tyRpyjTbYPDXWCcPp4mP2AB2fgm15lvQmL8fjy7tlCbm0gTSjISFmOQfP3AEuzCCg1hA3S1oqkuxFW24Ap+W3a2WxWkA9w+8HmK+BkBQa45iz5nPyp7FCzmIrcbB0u/rgPk19uGXeB6AuqWsTKNRwOAfsE4+02pJfAawyczFmQPfA3Dec4dvth3CI79Vl6P1DppAq5HI+fvkr/9RNLALo2jgFOqdU8/sy/uwVnpbLY/PALYMvA/G9J9w8FrTYOj5Q3j6hV1SQ3xnbtXlAn9vamjiEezHk1iAOv/5Fyj95K3GAFyFtbK+1f5x/WPYsv10mPoPAZx+8sFlBI//ZlOG2+dzLFuNRcbfJ3/9h/EsdqGOMXRS54w65l+2FYK3o18ebZUqMgPYeRMM/n7aQ9eawPCp++XxJfNTXEm10o2/n16BUfMLPItnsJD/8y9xRAwuwzr5SpoK4jGA+360DDXzHcDMnfHgYo7g6ReNyL4FfGc6zXRoYpI3/oZwAD9BOwTtmqWMtarAXVgrf5E2YzwGsHnn1wFcOuvBk1cBybXgE0va+YZg2hFJEZe89Dc4ggE0MMx7/xSKuQkRjGAMF+AmGUi7QRwGsGXnW2HwxVSHPn4tiD2LF/ANwVSKtQ5K/vo/OX7tdyrf+Gstl8OIf8Va+UdN/vANYONT87F07w8A89LUB0+uBR9bKnJ4zjy+UZVatekDk7/+hzGMH6PJa7+cWuZZbvAExvBK3CJDmjThG8B9u65Dbex6zaGRXAse7NonT56VfFClTbWWwScowGs/TwZC8Dfol89rqwnbAL6z68Vojj0Ig4XagwMygifOGZVDnc/jqwC9euMreO2XUTjry7biYlyCbjmizRy2AWwZ2AhjrtAeejz++LUgHl/SKcDMNweZkldg0cTn/X+CYewDP2ZdXsuTD/1cgrVyf5YSwjWA+wf+EGLuzfUSPnlD8KmzD/FaMMPoJG/87cF+/BwdvPbLoJ+tJYI70C/Z/ggeexEX4M8mU8cZA/dBsDxX9cmrgCOdB/HYOXN4LahQMpmaJg6bHyF5+4+P+yqksxpawyHU8Ltpnvqbad8wDWDLwCoYc5sVMfmcgF7G5K//ExjCo/y8v148qys+irXysTwZwzOA+3d0QWoPATg7z8FPXCsjeOQlhteCKRSduPYbgMEo+FxFCsmchBjsxml4pYb+M10d4RnAlp1rYNBjVVReC6aWc/za7+c4gGf4oZ/UorkIFPwV+mVT3tRhGUCC+ULbg4DpzHvwk9Ynzwn86sUN4sNmUXYC85V83t+gnden1qcwbcJv4GK8Ed2S3ADk+gnMAHYm3+r7llwnnmnxxHMCxIdNrxAxX07GLkPSo2jiItwk2zKsPfnvno0kheSYjPlytSHxYTMrS8yXq6nT5RXcin65Srdo5ugwXgFMh/mypcDUPMSHnawsMV+upk2bdy/G8Du4WZ7SLpwpPgwDmA7zZUuBqXl4LXiSsvy8v6thU+ZNCfrUZPXfAGbFfGmOqoklPuw5tfh5f83guIzdicW4MO+139QCAzCAWTBfruRO3hA82DXEpwWBSdd+xHy5mrc0eRWYrzTpJmL8NoA0mC/NaTWxvBYcJ/oT86UZGmexKsyXpgq/DSAN5ktzWk3sxLXgY0s7ZayC3ypEzJdmWtzFZsB8aYrx1wA0mC/NiTWxVcaHEfOlmRSXsam+4CNrAX4aQBbMV1YFWq2rIj6MmK9WU1HM7zNivjTF+WkAWTBfmlNrYit4LchrP82AOIzNiPnSVOSfAeTCfGmOromtED6M136awXAZmxnzpSnKPwPIg/nSnFwTWxV8WDINBqPmp3iWmC/NgFiPzYX50lTjlwHYwHxpTq+JrQI+bALztRvzAMzRyMNYiwrkxHxpKvHHAGxhvjSn18TGjg8j5kszDe5iLWC+NMX5YwA2MV8aBTSxMb8hSMyXZhJcxn4Ea+UTLjeYnNsPA3CC+XIkYYzXgsR8ORoWddofYzGW2f68/2xV+GEALjBfau1TLogQH0bMV8reuw6zhPnSlFm+AbjEfGmU0MTG9JwAMV+azruM/QbWyp+63GC63B4YgEPMlys1J+PDQv5WIWK+XE2INq9VzJdm83INoAjMl0YNTWwM14LHMF9D41/rPf7sH39KUmAd1sr7yti7PAMoEvPlStmQ8WHEfLmaCm1e65gvTQHlGUCRmC+NIprYgK8F+Xl/TaMdxjrAfGmqLccANj98JjD6IIDTNcX6GRsgPoyf9/dllLZhMS4u8tpv6sHLMYAtJWC+XLU8QHwYMV+uhkGZV/AG9MvdylVWw4s3gDIxX1alm5QspGtBYr5cTYE2rzPMl6aQ4g2gTMyXRhlNbCj4MGK+NF11F+sY86UpvFgD2PzDbkD+U1NgMLEhfKsQMV++jJNTzJfmkMUZgE+YL41CmlifnxMg5kvTSXexBWC+NMUXZwA+Yb40CmliPb4W5LWfppFOY1dhrax3uoMieTEGkGC+xsa2A+OfOIv8x0N8GK/9fJm5BPP1Rza+1tvWgYoxAB8xX7YUnJrHN3wYMV+uOq3NWxjmS1OYewPwGfOlUUoTm1wLPv2iEdm3YAFqmoUOYicwXz9HBwTtDnZgyjQKFIj5SlPORIxbA/Ad86VRShPrCz6MmC9N11zG7kUbfh+flt0uN8mS260BhID5yqJamjXJG4J7ztyPPYsXSA1udZ6pHmK+0nTKfYzBtVgna9xvpN/B3WBuHViEpkk+73+2vqxIVpR5LUjMly9DVDjmS3NwdwYQEuZLo5gmtkR8GDFfmkY5jC0B86U5jRsD2DzwCgAPAKZTU0yUsWU8J0DMly+jVArmS3N4RwYQIOZLo5omtuhrQWK+NN1xGVsa5ktzKPsGEDLmS6OcJrZIfNgxzNc+/BLPI+ZL0yTrsaVhvjQnsWsAMWC+NOppYkfbD+Kxc+bI0XqHs88GEPOl6Yi72OTz/k2cj5vlKXeb2Mls1wBiwHzZ0fXkLAU8J8DP+7tqnjKvwXuwTm5Wriol3J4BRIX5ctULh/gwft7fVdO0ebfhYvwBuuWIdmEZ8fYMICbMl6tOOMSHPXfttwcLnf0Xw5UuMeX1APOlkdOOAcSI+dKoqIl1cS1IzJemAy5jvcB8aQ6Y3wCSz/ufOfA1AJdqNq5s7ORvFWpibu6/1sR8+TFKCeariWVYJw/7UVC6KvIbQMyYr3Qa6qNs4sOI+dLr72aFN5gvzfHyGUAVMF8aNTWxNr5ViNd+GsXdxRrsxhjOxy0y5G4TN5nzGcCWgY/CmNVuSos8q4VrQV77eTMjXmG+NKpkN4BKYb40kmpic1wL8tpPI7TLWO8wX5rDZjeAKmG+NIpqYo8/JyCPL5kPoC31UmK+UkvlONBLzJfmzNkMoIqYL42qmtgs+LAJzNduzAMwR7MdYy0qILgV/XKVxYyFp9IbQPJ5/zMG7oVgeeHVxrjhxLXgE0vaUz0nQMyXL1OwF4Jl6JdHfSkoSx16A6gy5iuLwmnWHL8WTIUPI+YrjaLuYzzGfGkOrzMAYr402upi0+DDiPnSaeoueicW48Iyv9bb1tF0BkDMly3dT85zHB+GJ85aOBNElJgvd/KrMhtchnXyFdUaT4PTG8Dm7S8F2h4k5stlJ2f5ViFivlwKr8ntPeZLc5j0BsC//hpds8XOhA8j5iubnrZXGRyGwXLcJNtspy4rX3oD2Lzz63zgp4A2TYcPI+arAOFTbdGPtfL+VJGBBNEAfGvU1G8VSv7xH0UDuzCKBk7J/fSgb+cNpZ6AMF8aSdMbQBW+3lujnMvYSc8JoA0Gj2A/nsQC1PnP36Xss+YOCPOl0Si9Ady/owuofZUfANLImydWjuCRl4zi0BxgJwQG/I6FPHLmWxsU5ktz1PQGkGRNTKBWvxoGbwfMGQD/ImnEnj5W6sfw3ebE7xE+hg87iK1nCfaiE0Kt82udMYPgTeiXuzOu9nqZzgAmjpJ8HPg3diyEaU//AIvXMpRYXN3MxVhzPppy4ld3i0k+54+ODwx8GCPNZSVWWO2ta/W7Gjsuf1esImQzgFjV8PBc7afe+Hoxo//rYWnxl9TW1mjWasuO7O3ZFethaQABdLZjUd8mwFweQKlxlWhwQ2Oo90NxHerE09AAAuju3MV9L68Z8wCAhBvAn2IU2N2oN87FM6ufLWa7cnahAZSju3rXjq4110NwnXohF2RTwOCKxlDvHdkWh7OKBhBIr0499V8WHWk7krwKWBpIySGXeU9jsPEGYPVoyIdIUzsNII1KnsR0dq15mxF8wZNyYi3jqJjmJSND122J9YCTz0UDCKzLHYvWfBPAawMrO6RyP9cY7I322m9qI2gAIY1mAgBcuObcupjvQqQjsNK9L9cAQ/Xa2CuG93zoSe+LtVQgDcCSkEWm6ey6ca0ReW+Re1ZhLzGmd2To2r4qnHXijDSAALs977Trz2g26w8BOD3A8r0sWYDtI4PzLgSuPuxlgY6KogE4EtZ12vbFfVeLMZ9xvU9V8huDNx0e6v3vqpyXrwCC73R/e+ei4e8Z4Nzgj1LyAcTgyyNDvW8uuYxStucrgFJkt7Pp+HMCbcLnBPLIaUxjzMhFR/f1bs+TJtS1NIBQO3e8bj4nkK+BBvKpw4M91+TLEu5qGkC4vRuvnM8J5GmgPDZ3dM55Bw58YDBPlpDX0gBC7t7EqwA+J5Cxi3JVY7Dn1oyLo1hGA4igjXxOIFMTtzYG5/1J1a79pipFA8g0O/4t6ljU907AfN6/yrysaAw189rGnmu/5WV1BRZFAyhQbLdbrW7rWNTxbYDf2txaZ7mzMdjT3Tou/ggaQEQ97uy64dVGavcmjwxEdCzbRzlk6rVXHX7mmp/aThxiPhpAiF2bpeaOrjUbILgysmNZPI78c2Ow5+MWEwadigYQdPtOLr5jwafOMfWxHwjQFdnRbBynEpgvjVA0AI1agcR2dt3YY0TWBFJuYWWKwdtHhnr/o7ANA9iIBhBAk9QlPn/1KR1jHQk+7GXqtfEuuKfx2Z7Xo1vG4j2i/mQ0AL1mQazoXNT3lwbmziCKdV/k0VpNlg/v6fm++63C2oEGEFa/VNUSH/acXJXCfGmGhAagUSuw2Hmn9Z3fbJqtFb8W/HWtNnZelTBfmjGlAWjUCjC26vgwI/L+w3t7+gNsXSEl0wAKkbm8TaqMD6sq5kszbTQAjVqBxlYVH1ZVzJdmTGkAGrWCja0ePqzKmC/NmNIANGoFHFspfJgx0X+tt61RpAHYUjKAPJ1da+4ygssCKDVXiVXHfGnEowFo1Ao8dhwf1mxui/tbhYj50owpDUCjVgSx7Yv6PikwH4zgKDMcgZgvTW9pABq1Iog9hg87+hBgXhTBcaYeYWtjsPGaKnytt63e0QBsKRlQnkjxYcR8ZZhBGkAG0cJfEiE+zGBjY6h3Rfi9KfYENIBi9fZmt+P4sIQhWPemqOyFHMJY/ZWN/R/8RfYU1VxJA6hm38dPHQ8+jJivrGNMA8iqXATrEnwY6mM/BDA/4OM83Kg3LsAzq58N+AyllU4DKE16PzbuWNT3EcB8zI9q9FUQ86XXbPIKGkA+/cJfHTY+7J7GYO/rwm9CeSegAZSnvTc7d3ateZsRfMGbgtIVQsxXOp1mjaIBWBAxhhTB4cNEPtvY2/N3MWhf5hloAGWq79HegeHDiPmyNDs0AEtCxpCmY3HfLTDm3b6fhZgvex2iAdjTMvhMIeDDiPmyO2Y0ALt6Bp/Nd3yYGTVvOHzg2ruDF9qTA9AAPGmEP2X4iw8j5sv+lNAA7GsafEZP8WGHmiIXHNnbsyt4gT06AA3Ao2b4VIpv+DBivtxMBw3Aja7BZ/ULH0bMl6uBogG4UjaCvP7gw4j5cjVONABXykaQ1xN8GDFfDmeJBuBQ3BhSl4wPGxPTfM3I0HVbYtDSxzPQAHzsilc1lYgPI+bL+STQAJxLHP4GHafd+Mdoyj1F4sMMMCRj9d8j5svt/NAA3OobTfai8WFiTO/I0LV90Qjo6UFoAJ42xreyCsaHEfNV0ADQAAoSOoZtisKHCeTykcGeL8agme9noAH43iGf6juGD9sOYKnDsoj5ciju1NQ0gALFjmErp/gwYxpjRi46uq83MRn+FKAADaAAkaPaYpOpd7y7L3kc97W2zyXGrBsZuvZ9tvMy38wK0AA4HWoFHOHDiPlSdyL/AhpAfg0rmcE2PoyYr3LGiAZQju7B72oTH0bMV3njQAMoT/vgd7aFDyPmq7xRoAGUp30EO9vAh8mdjcGe7gjECPIINIAg2+ZP0e1da/5cBF/JWNEhU6+96vAz1/w043ouy6kADSCngFwOZMaHGdzQGOr9EDUsTwEaQHnaR7NzRnzY7ka9cS6/1rvcMaABlKt/NLur8WEGVzSGeu+IRoBAD0IDCLRxvpWtxIcR8+VJA2kAnjQihjJS4sOOimleQsyXHx2nAfjRh0iqSIUP+1xjsPddkRw4+GPQAIJvoV8HOP6cwLcAzJ+msofnjs599YEDHxj0q+rqVkMDqG7vnZ38+FeL3TSFG7DV1GsreefvTPZMiWkAmWTjolYKjINEx2QVBGcayIOoy+f4j7+VasX/ngZQvObckQp4owANwJtWsBAqULwCNIDiNeeOVMAbBWgA3rSChVCB4hWgARSvOXekAt4oQAPwphUshAoUr8D/A82GpoiIheLfAAAAAElFTkSuQmC'; var dataURLtoBlob = function (dataurl) { var arr = dataurl.split(','); var mime = arr[0].match(/:(.*?);/)[1]; var bstr = atob(arr[1]); var n = bstr.length; var u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }; 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) { try { var initCos = new COS({ SecretId: config.SecretId, SecretKey: config.SecretKey, ForcePathStyle: true, }); putFile(initCos, done, false); } catch (e) { assert.ok(e.message === 'ForcePathStyle is not supported'); done(); } }); 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('getStsCOS 使用临时密钥 putObject', function (done) { getStsCOS.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); oldTempCOS.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(); } ); }); test('getStsCOS 使用下发的签名 putObject', function (done) { getSignCOS.putObject( { Bucket: config.Bucket, Region: config.Region, Key: '1.txt', Body: '12345', }, function (err, data) { assert.ok(!err); done(); } ); }); test('getAuthorization 使用下发的签名 sliceUploadFile 没权限', function (done) { const file = createFileSync(20 * 1024 * 1024); getSignCOS.sliceUploadFile( { Bucket: config.Bucket, Region: config.Region, Key: '1.txt', Body: file, }, function (err, data) { assert.ok(err); done(); } ); }); test('推荐初始化方式 putObject 成功', function (done) { const cos = new COS({ SecretId: sts.TmpSecretId, SecretKey: sts.TmpSecretKey, SecurityToken: sts.SecurityToken, StartTime: sts.StartTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: sts.ExpiredTime, // 时间戳,单位秒,如:1580000000 }); cos.putObject( { Bucket: config.Bucket, Region: config.Region, Key: tempCOSPrefix + '1.txt', Body: '12345', }, function (err, data) { console.log(' putObject 成功', err || data); assert.ok(!err); done(); } ); }); test('推荐初始化方式 putObject invalid StartTime', function (done) { const cos = new COS({ SecretId: sts.TmpSecretId, SecretKey: sts.TmpSecretKey, SecurityToken: sts.SecurityToken, StartTime: sts.StartTime * 1000, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: sts.ExpiredTime, // 时间戳,单位秒,如:1580000000 }); cos.putObject( { Bucket: config.Bucket, Region: config.Region, Key: tempCOSPrefix + '1.txt', Body: '12345', }, function (err, data) { assert.ok(err); done(); } ); }); test('推荐初始化方式 putObject invalid ExpiredTime', function (done) { const cos = new COS({ SecretId: sts.TmpSecretId, SecretKey: sts.TmpSecretKey, SecurityToken: sts.SecurityToken, StartTime: sts.StartTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: sts.ExpiredTime * 1000, // 时间戳,单位秒,如:1580000000 }); cos.putObject( { Bucket: config.Bucket, Region: config.Region, Key: tempCOSPrefix + '1.txt', Body: '12345', }, function (err, data) { assert.ok(err); done(); } ); }); test('推荐初始化方式 getObjectUrl invalid StartTime', function (done) { const cos = new COS({ SecretId: sts.TmpSecretId, SecretKey: sts.TmpSecretKey, SecurityToken: sts.SecurityToken, StartTime: sts.StartTime * 1000, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误 ExpiredTime: sts.ExpiredTime, // 时间戳,单位秒,如:1580000000 }); cos.getObjectUrl( { Bucket: config.Bucket, Region: config.Region, Key: tempCOSPrefix + '1.txt', Expires: Date.now() * 1000, }, function (err, data) { console.log('getObjectUrl invalid ExpiredTime', 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('兼容性测试', function () { test('getBucketACL 老用法', function (done) { cos.getBucketACL( { Bucket: config.Bucket, Region: config.Region, }, function (err, data) { assert.ok(!err); done(); } ); }); }); 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: Date.now().toString(36) + config.Bucket, 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) { if (err) { done(); return; } let AuthData = cos.getAuth({ SecretId: config.SecretId, SecretKey: config.SecretKey, Method: 'get', Key: key, Scope: [ { action: 'GetObject', bucket: config.Bucket, region: config.Region, prefix: key, }, ], }); 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: true, Expires: 8000000, }, function (err, data) { expect(typeof data.Url).toBe('string'); err ? done(err) : done(); } ); tempCOS.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() options.AppId', function (done) { var filename = '/1m.zip'; const file = createFileSync(1 * 1024 * 1024); var cos = new COS({ SecretId: config.SecretId, SecretKey: config.SecretKey, AppId, UseRawKey: true, }); cos.putObject( { Bucket: BucketShortName, Region: config.Region, Key: filename, Body: file, }, function (err, data) { assert.ok(!err); done(); } ); }); test('putObject() options.CompatibilityMode', function (done) { var filename = '/1m.zip'; const file = createFileSync(1 * 1024 * 1024); var cos = new COS({ SecretId: config.SecretId, SecretKey: config.SecretKey, CompatibilityMode: true, }); cos.putObject( { Bucket: BucketShortName, Region: config.Region, Key: filename, Body: file, }, function (err, data) { assert.ok(err); done(); } ); }); 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(); } ); }); test('putObject() error Body', function (done) { cos.putObject( { Bucket: BucketShortName, AppId: AppId, Region: config.Region, Key: COS.util.encodeBase64('转base64', true), Body: { a: 1 }, }, function (err, data) { assert.ok(err); done(); } ); }); test('putObject() missing Key', function (done) { try { cos.putObject( { Bucket: BucketShortName, AppId: AppId, Region: config.Region, Body: file, }, function (err, data) {} ); } catch (e) { assert.ok(e.message === 'file is not defined'); 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) { if (err) { done(); return; } cos.sliceUploadFile( { Bucket: config.Bucket, Region: config.Region, Key: filename, Body: blob, Headers: { 'x-cos-traffic-limit': 8192000000, }, onTaskReady: function (taskId) { console.log(taskId); }, onProgress: function (info) { lastPercent = info.percent; }, }, function (err, data) { console.log('sliceUploadFile', err ? 'failed' : 'success'); if (err) { done(); return; } cos.headObject( { Bucket: config.Bucket, Region: config.Region, Key: filename, }, function (err, data) { console.log('headObject', err ? 'failed' : 'success'); const success = data && data.headers && parseInt(data.headers['content-length'] || 0) === fileSize; console.log(`data.headers['content-length']`, data.headers['content-length'], fileSize, success); expect(success); done(); } ); } ); } ); }); test('sliceUploadFile(),pauseTask(),restartTask()', function (done) { var filename = Date.now().toString() + '-10m.zip'; var blob = util.createFile({ size: 1024 * 1024 * 10 }); var paused = false; var updateFn = function (info) { var task = info.list.find((item) => item.Key === filename); if (task && task.state === 'success') { console.log('任务成功'); cos.off('list-update', updateFn); assert.ok(1); done(); } }; cos.abortUploadTask( { Bucket: config.Bucket, Region: config.Region, Key: filename, Level: 'file', }, function (err, data) { if (err) { done(); return; } 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.3) { cos.pauseTask(TaskId); paused = true; console.log('任务暂停'); cos.on('list-update', updateFn); setTimeout(function () { if (paused) { console.log('任务重启'); cos.restartTask(TaskId); } }, 10); } }, }, function (err, data) { assert.ok(1); done(); } ); } ); }); 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) { assert.ok(!err); done(); } ); 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) { var taskId; cos.sliceUploadFile( { Bucket: config.Bucket, Region: config.Region, Key: filename, Body: blob, onTaskReady: function (id) { taskId = id; }, onProgress: function (progressData) { if (progressData.percent >= 0.3) { cos.pauseTask(taskId); console.log('pause task'); cos.sliceUploadFile( { Bucket: config.Bucket, Region: config.Region, Key: filename, Body: blob, TaskReady: function (id) { console.log('TaskReady', id); }, }, function (err, data) { assert.ok(!err); done(); } ); } }, }, 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() 续传时远程为 0', function (done) { var taskId; var paused = false; cos.sliceUploadFile( { Bucket: config.Bucket, Region: config.Region, Key: filename, Body: blob, onTaskReady: function (id) { taskId = id; }, onProgress: function (progressData) { if (!paused && progressData.percent >= 0.3) { cos.pauseTask(taskId); paused = true; setTimeout(() => { if (paused) { var blob = util.createFile({ size: 1024 * 1024 * 20 }); cos.sliceUploadFile( { Bucket: config.Bucket, Region: config.Region, Key: filename, Body: blob, }, function (err, data) { assert.ok(!err); done(); } ); } }, 1000); } }, }, 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('headBu