空白格 3 лет назад
Сommit
aed68bafe1
100 измененных файлов с 68934 добавлено и 0 удалено
  1. BIN
      .DS_Store
  2. 16 0
      .hbuilderx/launch.json
  3. 49 0
      App.vue
  4. 122 0
      components/trtc-calling/index.scss
  5. 541 0
      components/trtc-calling/index.vue
  6. 6 0
      config/config.js
  7. 447 0
      config/tim/commen.js
  8. 44 0
      config/tim/tim.js
  9. 15 0
      config/tim/trtc-calling.js
  10. 24 0
      config/tim/user.js
  11. 14 0
      index.html
  12. 44 0
      main.js
  13. 75 0
      manifest.json
  14. 55 0
      node_modules/cos-js-sdk-v5/.github/workflows/auto-changelog.yml
  15. 893 0
      node_modules/cos-js-sdk-v5/CHANGELOG.md
  16. 21 0
      node_modules/cos-js-sdk-v5/LICENSE
  17. 111 0
      node_modules/cos-js-sdk-v5/README.md
  18. 17 0
      node_modules/cos-js-sdk-v5/bower.json
  19. 79 0
      node_modules/cos-js-sdk-v5/csp/AllowAction.md
  20. 7 0
      node_modules/cos-js-sdk-v5/csp/README.md
  21. 1936 0
      node_modules/cos-js-sdk-v5/csp/api.md
  22. 156 0
      node_modules/cos-js-sdk-v5/csp/auth-json.php
  23. 651 0
      node_modules/cos-js-sdk-v5/csp/csp.html
  24. 80 0
      node_modules/cos-js-sdk-v5/csp/start.md
  25. 1603 0
      node_modules/cos-js-sdk-v5/csp/test.html
  26. 40 0
      node_modules/cos-js-sdk-v5/demo/common/async.js
  27. 155 0
      node_modules/cos-js-sdk-v5/demo/common/cos-auth.js
  28. 1 0
      node_modules/cos-js-sdk-v5/demo/common/cos-auth.min.js
  29. 2 0
      node_modules/cos-js-sdk-v5/demo/common/jquery-3.3.1.min.js
  30. 29 0
      node_modules/cos-js-sdk-v5/demo/common/lodash.core.min.js
  31. 6 0
      node_modules/cos-js-sdk-v5/demo/common/vue.min.js
  32. BIN
      node_modules/cos-js-sdk-v5/demo/cors.png
  33. 53 0
      node_modules/cos-js-sdk-v5/demo/crc64.html
  34. 17990 0
      node_modules/cos-js-sdk-v5/demo/crc64.js
  35. 1890 0
      node_modules/cos-js-sdk-v5/demo/demo.js
  36. 1 0
      node_modules/cos-js-sdk-v5/demo/empty.html
  37. 19 0
      node_modules/cos-js-sdk-v5/demo/folder/index.html
  38. 38 0
      node_modules/cos-js-sdk-v5/demo/index.html
  39. 101 0
      node_modules/cos-js-sdk-v5/demo/mime-limit.html
  40. 144 0
      node_modules/cos-js-sdk-v5/demo/policy-form.html
  41. 137 0
      node_modules/cos-js-sdk-v5/demo/policy-post.html
  42. 66 0
      node_modules/cos-js-sdk-v5/demo/queue/index.html
  43. 77 0
      node_modules/cos-js-sdk-v5/demo/queue/index.js
  44. 78 0
      node_modules/cos-js-sdk-v5/demo/queue/style.css
  45. 170 0
      node_modules/cos-js-sdk-v5/demo/slice-task.html
  46. 129 0
      node_modules/cos-js-sdk-v5/demo/slice.html
  47. 134 0
      node_modules/cos-js-sdk-v5/demo/sts-form.html
  48. 126 0
      node_modules/cos-js-sdk-v5/demo/sts-post.html
  49. 129 0
      node_modules/cos-js-sdk-v5/demo/sts-put-server-key.html
  50. 128 0
      node_modules/cos-js-sdk-v5/demo/sts-put.html
  51. 9804 0
      node_modules/cos-js-sdk-v5/demo/vueDemo/cos-js-sdk-v5.js
  52. 56 0
      node_modules/cos-js-sdk-v5/demo/vueDemo/index.html
  53. 185 0
      node_modules/cos-js-sdk-v5/demo/vueDemo/index.js
  54. 6 0
      node_modules/cos-js-sdk-v5/demo/vueDemo/vue.min.js
  55. 9943 0
      node_modules/cos-js-sdk-v5/dist/cos-js-sdk-v5.js
  56. 1 0
      node_modules/cos-js-sdk-v5/dist/cos-js-sdk-v5.min.js
  57. 2283 0
      node_modules/cos-js-sdk-v5/index.d.ts
  58. 2 0
      node_modules/cos-js-sdk-v5/index.js
  59. 128 0
      node_modules/cos-js-sdk-v5/lib/crypto.js
  60. 167 0
      node_modules/cos-js-sdk-v5/lib/json2xml.js
  61. 648 0
      node_modules/cos-js-sdk-v5/lib/md5.js
  62. 136 0
      node_modules/cos-js-sdk-v5/lib/request.js
  63. 166 0
      node_modules/cos-js-sdk-v5/lib/xml2json.js
  64. 70 0
      node_modules/cos-js-sdk-v5/package.json
  65. 171 0
      node_modules/cos-js-sdk-v5/server/qcloud-sts-sdk.php
  66. 263 0
      node_modules/cos-js-sdk-v5/server/sts.js
  67. 40 0
      node_modules/cos-js-sdk-v5/server/sts.php
  68. 1184 0
      node_modules/cos-js-sdk-v5/src/advance.js
  69. 60 0
      node_modules/cos-js-sdk-v5/src/async.js
  70. 3723 0
      node_modules/cos-js-sdk-v5/src/base.js
  71. 74 0
      node_modules/cos-js-sdk-v5/src/cos.js
  72. 34 0
      node_modules/cos-js-sdk-v5/src/event.js
  73. 104 0
      node_modules/cos-js-sdk-v5/src/session.js
  74. 255 0
      node_modules/cos-js-sdk-v5/src/task.js
  75. 724 0
      node_modules/cos-js-sdk-v5/src/util.js
  76. 24 0
      node_modules/cos-js-sdk-v5/test/index.html
  77. 436 0
      node_modules/cos-js-sdk-v5/test/qunit-2.4.0.css
  78. 5048 0
      node_modules/cos-js-sdk-v5/test/qunit-2.4.0.js
  79. 3844 0
      node_modules/cos-js-sdk-v5/test/test.js
  80. 35 0
      node_modules/cos-js-sdk-v5/test/watcher.js
  81. 104 0
      node_modules/cos-js-sdk-v5/webpack.config.js
  82. 73 0
      node_modules/tim-js-sdk/README.md
  83. 51 0
      node_modules/tim-js-sdk/package.json
  84. 1 0
      node_modules/tim-js-sdk/tim-js-friendship.js
  85. 1 0
      node_modules/tim-js-sdk/tim-js.js
  86. 94 0
      node_modules/trtc-calling-js/README.md
  87. 45 0
      node_modules/trtc-calling-js/package.json
  88. 1 0
      node_modules/trtc-calling-js/trtc-calling-js.js
  89. 84 0
      node_modules/trtc-js-sdk/README.md
  90. 51 0
      node_modules/trtc-js-sdk/package.json
  91. 1 0
      node_modules/trtc-js-sdk/trtc.esm.js
  92. 1 0
      node_modules/trtc-js-sdk/trtc.js
  93. 1 0
      node_modules/trtc-js-sdk/trtc.umd.js
  94. 62 0
      node_modules/tsignaling/README.md
  95. 51 0
      node_modules/tsignaling/package.json
  96. 10 0
      node_modules/tsignaling/tsignaling-js.js
  97. 10 0
      node_modules/tsignaling/tsignaling-wx.js
  98. 22 0
      node_modules/xmldom/.travis.yml
  99. 8 0
      node_modules/xmldom/LICENSE
  100. 0 0
      node_modules/xmldom/__package__.js

+ 16 - 0
.hbuilderx/launch.json

@@ -0,0 +1,16 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+  // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version": "0.0",
+    "configurations": [{
+     	"default" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"h5" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"type" : "uniCloud"
+     }
+    ]
+}

+ 49 - 0
App.vue

@@ -0,0 +1,49 @@
+<script>
+	export default {
+		mounted() {
+			/**官网有很多关于关于sdk 其他的监听方法(比如:有新的消息,用户资料更新等等)
+			 * 详情可对照: https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/SDK.html
+			 * 监听的含义:服务端发生了数据变更---前端全局可以接收到变更通知--前端就可以自动触发某个事件来更新相应数据
+			 * */
+			// 登录成功后会触发 SDK_READY 事件,该事件触发后,可正常使用 SDK 接口
+			this.tim.on(this.$TIM.EVENT.SDK_READY, this.onReadyStateUpdate, this);
+			// 收到新消息
+			this.tim.on(this.$TIM.EVENT.MESSAGE_RECEIVED, this.onReceiveMessage);
+			// 会话列表更新
+			this.tim.on(this.$TIM.EVENT.CONVERSATION_LIST_UPDATED, event => {
+				this.$store.commit("updateConversationList", event.data);
+			});
+		},
+		methods: {
+			onReadyStateUpdate({
+				name
+			}) {
+				const isSDKReady = name === this.$TIM.EVENT.SDK_READY ? true : false;
+				// 自动监听并更新 sdk 的ready 状态 (未登录是 notReady  登录后是ready)
+				this.$store.commit("toggleIsSDKReady", isSDKReady);
+				//sdk ready 后  肯定完成了登录操作    这里可以获取用户存储在im的基础信息/离线消息/黑名单列表
+			},
+
+			onReceiveMessage({
+				data: messageList
+			}) {
+				// this.handleAt(messageList);
+				this.$store.commit("pushCurrentMessageList", messageList);
+			}
+		},
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style lang="scss">
+	/*每个页面公共css */
+	@import "uview-ui/index.scss";
+</style>

+ 122 - 0
components/trtc-calling/index.scss

@@ -0,0 +1,122 @@
+@font-face {
+  font-family: "iconfont"; /* Project id 2965205 */
+  src: url('//at.alicdn.com/t/font_2965205_rpxbfelmxq.woff2?t=1637911677755') format('woff2'),
+       url('//at.alicdn.com/t/font_2965205_rpxbfelmxq.woff?t=1637911677755') format('woff'),
+       url('//at.alicdn.com/t/font_2965205_rpxbfelmxq.ttf?t=1637911677755') format('truetype');
+}
+
+.iconfont {
+  font-family: "iconfont" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+
+.icon-maikefeng-jingyin:before {
+  content: "\e697";
+}
+
+.icon-call:before {
+  content: "\e6dc";
+}
+
+.icon-guaduan:before {
+  content: "\e640";
+}
+
+.icon-mic-on-full:before {
+  content: "\e96b";
+}
+
+.icon-yuyin:before {
+  content: "\e6e1";
+}
+
+.icon-shipin:before {
+  content: "\e64f";
+}
+.calling {
+	height: 100vh;
+	width: 100%;
+	background-color: #7d7d7d;
+	position: fixed;
+	z-index: 1200;
+	
+	&-waiting {
+		position: relative;
+		height: calc(100% - 160rpx);
+		&-header {
+			width: 240rpx;
+			height: 240rpx;
+			margin: 160rpx auto 0;
+		}
+		&-username {
+			color: #fff;
+			font-size: 36rpx;
+			margin-top: 40rpx;
+			text-align: center;
+			font-family: 'PingFangSC-Regular, PingFang SC';
+		}
+		&-status {
+			color: #fff;
+			font-size: 30rpx;
+			margin-top: 30rpx;
+			text-align: center;
+			font-family: 'PingFangSC-Regular, PingFang SC';
+		}
+		&-button {
+			position: absolute;
+			bottom: 200rpx;
+			z-index: 1220;
+			display: flex;
+			justify-content: space-between;
+			width: 60%;
+			left: 20%;
+			&-passed {
+				background-color: #FA3534;
+				width: 120rpx;
+				height: 120rpx;
+				line-height: 120rpx;
+				text-align: center;
+				border-radius: 50%;
+				color: #fff;
+				.iconfont {
+					font-size: 60rpx;
+				}
+			}
+			&-mute {
+				background-color: #fff;
+				width: 120rpx;
+				height: 120rpx;
+				line-height: 120rpx;
+				text-align: center;
+				border-radius: 50%;
+				color: #2979ff;
+				.iconfont {
+					font-size: 50rpx;
+				}
+				.on {
+					color: #2979ff;
+				}
+				.off {
+					color: #c8c9cc;
+				}
+			}
+		}
+		&-userList {
+			display: flex;
+			justify-content: center;
+			margin-top: 160rpx;
+			&-item {
+				margin: 0 40rpx;
+				color: #fff;
+			}
+		}
+		&-duration {
+			margin-top: 50vh;
+			text-align: center;
+			color: #fff;
+		}
+	}
+}

+ 541 - 0
components/trtc-calling/index.vue

@@ -0,0 +1,541 @@
+<template>
+	<view class="calling" v-show="callingDialog">
+		<!-- 等待对方接受 -->
+		<view class="calling-waiting" v-if="dialling">
+			<view class="calling-waiting-header">
+				<u-avatar :src="defaultAvatar" size="240" mode="square"></u-avatar>
+			</view>
+			<view class="calling-waiting-status">
+				<view>正在呼叫{{ toAccount }}</view>
+			</view>
+			<view class="calling-waiting-button">
+				<view class="calling-waiting-button-passed" @click="handleDebounce(leave, 500)">
+					<view class="iconfont icon-guaduan"></view>
+				</view>
+				<view class="calling-waiting-button-mute" @click="micHandler">
+					<view class="iconfont icon-mic-on-full" :class="isMicOn ? 'on' : 'off'"></view>
+				</view>
+			</view>
+		</view>
+		<!-- 接收方 -->
+		<view class="calling-waiting" v-else-if="isDialled">
+			<view class="calling-waiting-header">
+				<u-avatar :src="defaultAvatar" size="240" mode="square"></u-avatar>
+			</view>
+			<view class="calling-waiting-status">
+				<view>{{ sponsor }}来电</view>
+			</view>
+			<view class="calling-waiting-button">
+				<view class="calling-waiting-button-mute" @click="handleDebounce(accept, 500)">
+					<view class="iconfont icon-call"></view>
+				</view>
+				<view class="calling-waiting-button-passed" @click="handleDebounce(leave, 500)">
+					<view class="iconfont icon-guaduan"></view>
+				</view>
+			</view>
+		</view>
+		<!-- 正在聊天 -->
+		<view class="calling-waiting" v-else-if="calling">
+			<view class="calling-waiting-userList">
+				<view class="calling-waiting-userList-item" v-for="(item, index) in invitedUserInfo" :key="index">
+					<u-avatar :src="item.avatar || defaultAvatar" size="120"></u-avatar>
+					<view style="text-align: center;margin-top: 30rpx;">
+						<text class="nick-text">{{ item.nick || item.userID }}</text>
+						<text v-if="item.isInvitedMicOn === true || item.isInvitedMicOn == undefined"
+							class="iconfont icon-yuyin"
+							style="color: #006FFF;font-size: 50rpx;margin-left: 10rpx;"></text>
+						<text v-else class="iconfont icon-maikefeng-jingyin"
+							style="color: #fff;font-size: 50rpx;margin-left: 10rpx;"></text>
+					</view>
+				</view>
+			</view>
+			<view class="calling-waiting-duration">
+				{{ formatDurationStr }}
+			</view>
+			<view class="calling-waiting-button">
+				<view class="calling-waiting-button-passed" @click="handleDebounce(leave, 500)">
+					<view class="iconfont icon-guaduan"></view>
+				</view>
+				<view class="calling-waiting-button-mute" @click="micHandler">
+					<view class="iconfont icon-mic-on-full" :class="isMicOn ? 'on' : 'off'"></view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				timeout: null,
+				callType: 1, //1:audio,2:video
+				Trtc: undefined,
+				isCamOn: true,
+				isMicOn: true,
+				isInvitedMicOn: true,
+				maskShow: false,
+				isLocalMain: true, // 本地视频是否是主屏幕显示
+				start: 0,
+				end: 0,
+				duration: 0,
+				hangUpTimer: 0, // 通话计时id
+				ready: false,
+				dialling: true, // 是否拨打电话中
+				calling: false, // 是否通话中
+				isDialled: false, // 是否被呼叫
+				inviteID: '',
+				inviteData: {},
+				sponsor: '', // 发起者
+				toAccount: '222', // 接收者
+				invitedUserID: [], //被邀请者
+				invitedNick: '',
+				invitedUserInfo: [],
+				defaultAvatar: 'https://imgcache.qq.com/open/qcloud/video/act/webim-avatar/avatar-3.png',
+				viewLocalDomID: '',
+				callingUserList: [], // 参加通话的人 ,不包括自己
+				callingType: 'C2C', //区分多人和C2C通话的UI样式
+				isStartLocalView: false, //本地是否开启
+				callingTips: {
+					callEnd: 1, //通话结束
+					callTimeout: 5
+				},
+				callingDialog: false,
+				callingInfo: {
+					type: 'C2C'
+				}
+			}
+		},
+		// onShow() {
+		// 	this.initListener();
+		// },
+		onHide() {
+			this.removeListener();
+		},
+		watch: {
+			callingUserList: {
+				handler(newValue) {
+					console.log(newValue)
+				},
+				deep: true,
+				immediate: true
+		 }
+		},
+		computed: {
+			formatDurationStr() {
+				return this.$format.formatDuration(this.duration)
+			}
+		},
+		methods: {
+			handleDebounce(func, wait) {
+				let context = this
+				let args = arguments
+				if (this.timeout) clearTimeout(this.timeout)
+				this.timeout = setTimeout(() => {
+					func.apply(context, args)
+				}, wait)
+			},
+			accept() {
+				this.trtcCalling.accept({
+					inviteID: this.inviteID,
+					roomID: this.inviteData.roomID,
+					callType: this.inviteData.callType
+				}).then((res) => {
+					this.changeState('calling', true);
+					this.dialling = false;
+					this.calling = true;
+					this.isDialled = false;
+					console.log('接收信息res', res)
+					// this.currentUserProfile.nick = res.data.message.nick
+				})
+			},
+			leave() { // 离开房间,发起方挂断
+				this.isMicOn = true
+				this.isCamOn = true
+				this.maskShow = false
+				this.isStartLocalView = false
+				this.dialling = false;
+				this.calling = false;
+				this.isDialled = false;
+				this.callingDialog = false
+				if (!this.calling) { // 还没有通话,单方面挂断
+					this.trtcCalling.hangup().then((res) => {
+						// this.currentUserProfile.nick = res.data.message.nick
+						this.changeState('dialling', false)
+						clearTimeout(this.timer)
+					})
+					return
+				}
+				this.hangUp() // 通话一段时间之后,某一方面结束通话
+			},
+			hangUp() { // 通话一段时间之后,某一方挂断电话
+				this.changeState('calling', false)
+				this.trtcCalling.hangup();
+				this.callingDialog = false
+				uni.showToast({
+					title: '已挂断',
+					icon: 'none'
+				})
+			},
+			openDialog() {
+				this.callingDialog = true;
+				this.dialling = true;
+				this.calling = false;
+				this.isDialled = false;
+			},
+			initListener() {
+				// sdk内部发生了错误
+				this.trtcCalling.on(this.TRTCCalling.EVENT.ERROR, this.handleError)
+				// 被邀请进行通话
+				this.trtcCalling.on(this.TRTCCalling.EVENT.INVITED, this.handleNewInvitationReceived)
+				// 有用户同意进入通话,那么会收到此回调
+				this.trtcCalling.on(this.TRTCCalling.EVENT.USER_ENTER, this.handleUserEnter)
+				// 如果有用户同意离开通话,那么会收到此回调
+				this.trtcCalling.on(this.TRTCCalling.EVENT.USER_LEAVE, this.handleUserLeave)
+				// 用户拒绝通话
+				this.trtcCalling.on(this.TRTCCalling.EVENT.REJECT, this.handleInviteeReject)
+				//邀请方忙线
+				this.trtcCalling.on(this.TRTCCalling.EVENT.LINE_BUSY, this.handleInviteeLineBusy)
+				// 作为被邀请方会收到,收到该回调说明本次通话被取消了
+				this.trtcCalling.on(this.TRTCCalling.EVENT.CALLING_CANCEL, this.handleInviterCancel)
+				// 重复登陆,收到该回调说明被踢出房间
+				this.trtcCalling.on(this.TRTCCalling.EVENT.KICKED_OUT, this.handleKickedOut)
+				// 作为邀请方会收到,收到该回调说明本次通话超时未应答
+				this.trtcCalling.on(this.TRTCCalling.EVENT.CALLING_TIMEOUT, this.handleCallTimeout)
+				// 邀请用户无应答
+				this.trtcCalling.on(this.TRTCCalling.EVENT.NO_RESP, this.handleNoResponse)
+				// 收到该回调说明本次通话结束了
+				this.trtcCalling.on(this.TRTCCalling.EVENT.CALLING_END, this.handleCallEnd)
+				// 远端用户开启/关闭了摄像头, 会收到该回调
+				this.trtcCalling.on(this.TRTCCalling.EVENT.USER_VIDEO_AVAILABLE, this.handleUserVideoChange)
+				// 远端用户开启/关闭了麦克风, 会收到该回调
+				this.trtcCalling.on(this.TRTCCalling.EVENT.USER_AUDIO_AVAILABLE, this.handleUserAudioChange)
+			},
+			removeListener() {
+				this.trtcCalling.off(this.TRTCCalling.EVENT.ERROR, this.handleError)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.INVITED, this.handleNewInvitationReceived)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.USER_ENTER, this.handleUserEnter)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.USER_LEAVE, this.handleUserLeave)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.REJECT, this.handleInviteeReject)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.LINE_BUSY, this.handleInviteeLineBusy)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.CALLING_CANCEL, this.handleInviterCancel)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.KICKED_OUT, this.handleKickedOut)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.CALLING_TIMEOUT, this.handleCallTimeout)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.NO_RESP, this.handleNoResponse)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.CALLING_END, this.handleCallEnd)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.USER_VIDEO_AVAILABLE, this.handleUserVideoChange)
+				this.trtcCalling.off(this.TRTCCalling.EVENT.USER_AUDIO_AVAILABLE, this.handleUserAudioChange)
+			},
+			handleError() {
+				console.log('Error')
+			},
+			handleUserVideoChange() {},
+			handleUserAudioChange(payload) {
+				const _index = this.invitedUserInfo.findIndex(item => item.userID === payload.userID)
+				if (_index >= 0) {
+					this.invitedUserInfo[_index].isInvitedMicOn = payload.isAudioAvailable
+				}
+			},
+			// 双方,通话已建立, 通话结束
+			handleCallEnd({
+				userID,
+				callEnd
+			}) {
+				// 自己挂断的要补充消息  被邀请者都无应答时结束
+				// 历史消息中没有通话结束
+				if (userID === this.userID && this.invitedUserID.length === 0 || this.callingUserList === 0) {
+					this.sendMessage(userID, callEnd, this.callingTips.callEnd)
+				}
+				this.changeState('dialling', false)
+				this.isMicOn = true
+				this.isCamOn = true
+				this.maskShow = false
+				this.isStartLocalView = false
+
+			},
+			// 自己超时且是邀请发起者,需主动挂断,并通知上层对端无应答
+			handleNoResponse({
+				sponsor,
+				userIDList
+			}) { //邀请者
+				if (sponsor === this.userID) {
+					userIDList.forEach((userID) => {
+						this.setCallingstatus(userID)
+					})
+					if (userIDList.indexOf(this.userID) === -1) { //当超时者是自己时,添加消息
+						this.sendMessage(userIDList, '', this.callingTips.callTimeout)
+					}
+				}
+			},
+			// 当自己收到对端超时的信令时,或者当我是被邀请者但自己超时了,通知上层通话超时
+			// case: A呼叫B,B在线,B超时未响应,B会触发该事件,A也会触发该事件
+			handleCallTimeout({
+				userIDList
+			}) {
+				if (this.calling) {
+					return
+				}
+				if (this.userID === this.sponsor) { // 该用户是邀请者
+					userIDList.forEach((userID) => {
+						this.setCallingstatus(userID) //超时未接听
+					})
+					return
+				}
+				//用户是被邀请者
+				if (userIDList.indexOf(this.userID) > -1) { //当超时者是自己时,添加消息
+					//会话列表切换后发消息
+					this.toAccount && this.sendMessage(this.userID, '', this.callingTips.callTimeout)
+				}
+				this.changeState('isDialled', false)
+			},
+			handleKickedOut() {
+				// 重复登陆,被踢出房间
+			},
+			// 自己超时且是邀请发起者,需主动挂断,并通知上层对端无应答
+			handleNoResponse({
+				sponsor,
+				userIDList
+			}) { //邀请者
+				if (sponsor === this.userID) {
+					userIDList.forEach((userID) => {
+						this.setCallingstatus(userID)
+					})
+					if (userIDList.indexOf(this.userID) === -1) { // 当超时者是自己时,添加消息
+						this.sendMessage(userIDList, '', this.callingTips.callTimeout)
+					}
+				}
+
+			},
+			// 当自己收到对端超时的信令时,或者当我是被邀请者但自己超时了,通知上层通话超时
+			// case: A呼叫B,B在线,B超时未响应,B会触发该事件,A也会触发该事件
+			handleCallTimeout({
+				userIDList
+			}) {
+				if (this.calling) {
+					return
+				}
+				if (this.userID === this.sponsor) { // 该用户是邀请者
+					userIDList.forEach((userID) => {
+						this.setCallingstatus(userID) //超时未接听
+					})
+					return
+				}
+				//用户是被邀请者
+				if (userIDList.indexOf(this.userID) > -1) { //当超时者是自己时,添加消息
+					//会话列表切换后发消息
+					this.toAccount && this.sendMessage(this.userID, '', this.callingTips.callTimeout)
+				}
+				this.changeState('isDialled', false)
+			},
+			handleKickedOut() {},
+			// 通知被呼叫方,邀请被取消,未接通
+			handleInviterCancel() {
+				// 邀请被取消
+				this.changeState('isDialled', false)
+				uni.showToast({
+					title: '通话已取消',
+					icon: 'none'
+				})
+			},
+			// 通知呼叫方,对方在忙碌,未接通
+			handleInviteeLineBusy({
+				sponsor,
+				userID
+			}) {
+				// A call B,C call A, A在忙线, 拒绝通话,对于呼叫者C收到通知,XXX在忙线
+				if (sponsor === this.userID) {
+					this.setCallingstatus(userID)
+					uni.showToast({
+						title: '对方忙线',
+						icon: 'none'
+					})
+				}
+			},
+			setCallingstatus(userID) {
+				const _index = this.invitedUserID.indexOf(userID)
+				if (_index >= 0) {
+					this.invitedUserID.splice(_index, 1)
+				}
+				if (this.invitedUserID.length === 0) {
+					this.changeState('isDialled', false)
+					this.changeState('dialling', false)
+				}
+			},
+			// 通知呼叫方,未接通
+			//userID:invitee(被邀请者)
+			handleInviteeReject({
+				userID
+			}) {
+				if (this.userID === this.sponsor) {
+					// 发起者
+					this.setCallingstatus(userID)
+					uni.showToast({
+						title: '用户拒绝通话',
+						icon: 'none'
+					})
+				}
+			},
+			// 用户离开
+			handleUserLeave({
+				userID
+			}) {
+				console.log(this.callType)
+				if (this.callType === this.TRTCCalling.CALL_TYPE.AUDIO_CALL) {
+					// 语音通话
+					const _index = this.invitedUserInfo.findIndex(item => item.userID === userID)
+					if (_index >= 0) {
+						this.invitedUserInfo.splice(_index, 1)
+					}
+					return
+				}
+				const index = this.callingUserList.findIndex(item => item === userID)
+				if (index >= 0) {
+					this.callingUserList.splice(index, 1)
+				}
+				this.dialling = true;
+				this.calling = false;
+				this.isDialled = false;
+				this.callingDialog = false
+			},
+			// 被呼叫  接听方
+			async handleNewInvitationReceived(payload) {
+				console.log('接听方', payload)
+				this.inviteID = payload.inviteID
+				this.callingDialog = true
+				this.dialling = false;
+				this.calling = false;
+				this.isDialled = true;
+			},
+			// 双方建立连接
+			handleUserEnter({
+				userID
+			}) {
+				this.changeState('dialling', true)
+				this.isAccept()
+				// 判断是否为多人通话
+				if (this.callingUserList.length >= 2) {
+					this.callingType = this.$TIM.TYPES.CONV_GROUP
+				}
+				if (this.callingUserList.indexOf(userID) === -1) {
+					if (this.callType === this.TRTCCalling.CALL_TYPE.AUDIO_CALL) {
+						this.getUserAvatar(userID)
+					} else {
+						this.callingUserList.push(userID)
+					}
+				}
+				if (this.callType === this.TRTCCalling.CALL_TYPE.VIDEO_CALL) {
+					this.$nextTick(() => {
+						if (!this.isStartLocalView) {
+							this.startLocalView() //本地只开启一次
+						}
+						this.startRemoteView(userID) //远端多次拉流
+					})
+				}
+			},
+			/**
+			 *  播放本地流
+			 */
+			startLocalView() {
+				this.trtcCalling.startLocalView({
+					userID: this.userID,
+					videoViewDomID: 'local'
+				}).then(() => {
+					this.isStartLocalView = true
+				})
+			},
+			async sendMessage(userId, callEnd, callText) {
+				let call_text = ''
+				userId = Array.isArray(userId) ? userId.join(',') : userId
+				let messageData = {
+					to: this.toAccount,
+					from: userId,
+					conversationType: this.currentConversationType,
+					payload: {
+						data: '',
+						description: '',
+						extension: ''
+					}
+				}
+				const message = await this.$TIM.createCustomMessage(messageData)
+			},
+			/**
+			 * 播放远端流
+			 * @param {Object} userID
+			 */
+			startRemoteView(userID) {
+				this.trtcCalling.startRemoteView({
+					userID: userID,
+					videoViewDomID: `video-${userID}`
+				}).then(() => {
+
+				})
+			},
+			/**
+			 * 获取被呼叫者信息
+			 * @param {Object} userID
+			 */
+			getUserAvatar(userID) {
+				const _index = this.invitedUserInfo.findIndex(item => item.userID === userID)
+				if (_index >= 0) {
+					return
+				}
+				let _userIDList = [userID]
+				let promise = this.tim.getUserProfile({
+					userIDList: _userIDList // 请注意:即使只拉取一个用户的资料,也需要用数组类型,例如:userIDList: ['user1']
+				})
+				promise.then((imResponse) => {
+					if (imResponse.data[0]) {
+						this.invitedUserInfo.push(imResponse.data[0])
+					}
+				}).catch(() => {})
+			},
+			/**
+			 *  对方接听自己发起的电话
+			 */
+			isAccept() {
+				clearTimeout(this.timer)
+				this.changeState('calling', true)
+				clearTimeout(this.hangUpTimer)
+				this.resetDuration(0)
+				this.start = new Date()
+			},
+			resetDuration(duration) {
+				this.duration = duration
+				this.hangUpTimer = setTimeout(() => {
+					let now = new Date()
+					this.resetDuration(parseInt((now - this.start) / 1000))
+				}, 1000)
+			},
+			/**
+			 * 修改状态
+			 * @param {Object} state
+			 * @param {Object} boolean
+			 */
+			changeState(state, boolean) {
+				let stateList = ['dialling', 'isDialled', 'calling']
+				stateList.forEach(item => {
+					this[item] = item === state ? boolean : false
+				})
+				this.$store.commit('UPDATE_ISBUSY', stateList.some(item => this[
+					item]))
+				// 若stateList 中存在 true , isBusy 为 true
+			},
+			/**
+			 * 是否打开麦克风
+			 */
+			micHandler() {
+				if (this.isMicOn) {
+					this.trtcCalling.setMicMute(true)
+					this.isMicOn = false
+				} else {
+					this.trtcCalling.setMicMute(false)
+					this.isMicOn = true
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import './index.scss';
+</style>

+ 6 - 0
config/config.js

@@ -0,0 +1,6 @@
+const config = {
+	sdkAppId: 1400601414,
+	secretKey: '6d065252f0779d8a4a45020630b3507ac1c8f946669fc240b9818ed243e40547',
+	baseUrl: 'https://wx.hw.hongweisoft.com/veterans/app'
+}
+export default config

+ 447 - 0
config/tim/commen.js

@@ -0,0 +1,447 @@
+const commen = {}
+
+
+commen.emojiList = [
+	[{
+		"url": "100.gif",
+		alt: "[微笑]"
+	}, {
+		"url": "101.gif",
+		alt: "[伤心]"
+	}, {
+		"url": "102.gif",
+		alt: "[美女]"
+	}, {
+		"url": "103.gif",
+		alt: "[发呆]"
+	}, {
+		"url": "104.gif",
+		alt: "[墨镜]"
+	}, {
+		"url": "105.gif",
+		alt: "[哭]"
+	}, {
+		"url": "106.gif",
+		alt: "[羞]"
+	}, {
+		"url": "107.gif",
+		alt: "[哑]"
+	}, {
+		"url": "108.gif",
+		alt: "[睡]"
+	}, {
+		"url": "109.gif",
+		alt: "[哭]"
+	}, {
+		"url": "110.gif",
+		alt: "[囧]"
+	}, {
+		"url": "111.gif",
+		alt: "[怒]"
+	}, {
+		"url": "112.gif",
+		alt: "[调皮]"
+	}, {
+		"url": "113.gif",
+		alt: "[笑]"
+	}, {
+		"url": "114.gif",
+		alt: "[惊讶]"
+	}, {
+		"url": "115.gif",
+		alt: "[难过]"
+	}, {
+		"url": "116.gif",
+		alt: "[酷]"
+	}, {
+		"url": "117.gif",
+		alt: "[汗]"
+	}, {
+		"url": "118.gif",
+		alt: "[抓狂]"
+	}, {
+		"url": "119.gif",
+		alt: "[吐]"
+	}, {
+		"url": "120.gif",
+		alt: "[笑]"
+	}, {
+		"url": "121.gif",
+		alt: "[快乐]"
+	}, {
+		"url": "122.gif",
+		alt: "[奇]"
+	}, {
+		"url": "123.gif",
+		alt: "[傲]"
+	}],
+	[{
+		"url": "124.gif",
+		alt: "[饿]"
+	}, {
+		"url": "125.gif",
+		alt: "[累]"
+	}, {
+		"url": "126.gif",
+		alt: "[吓]"
+	}, {
+		"url": "127.gif",
+		alt: "[汗]"
+	}, {
+		"url": "128.gif",
+		alt: "[高兴]"
+	}, {
+		"url": "129.gif",
+		alt: "[闲]"
+	}, {
+		"url": "130.gif",
+		alt: "[努力]"
+	}, {
+		"url": "131.gif",
+		alt: "[骂]"
+	}, {
+		"url": "132.gif",
+		alt: "[疑问]"
+	}, {
+		"url": "133.gif",
+		alt: "[秘密]"
+	}, {
+		"url": "134.gif",
+		alt: "[乱]"
+	}, {
+		"url": "135.gif",
+		alt: "[疯]"
+	}, {
+		"url": "136.gif",
+		alt: "[哀]"
+	}, {
+		"url": "137.gif",
+		alt: "[鬼]"
+	}, {
+		"url": "138.gif",
+		alt: "[打击]"
+	}, {
+		"url": "139.gif",
+		alt: "[bye]"
+	}, {
+		"url": "140.gif",
+		alt: "[汗]"
+	}, {
+		"url": "141.gif",
+		alt: "[抠]"
+	}, {
+		"url": "142.gif",
+		alt: "[鼓掌]"
+	}, {
+		"url": "143.gif",
+		alt: "[糟糕]"
+	}, {
+		"url": "144.gif",
+		alt: "[恶搞]"
+	}, {
+		"url": "145.gif",
+		alt: "[什么]"
+	}, {
+		"url": "146.gif",
+		alt: "[什么]"
+	}, {
+		"url": "147.gif",
+		alt: "[累]"
+	}],
+	[{
+		"url": "148.gif",
+		alt: "[看]"
+	}, {
+		"url": "149.gif",
+		alt: "[难过]"
+	}, {
+		"url": "150.gif",
+		alt: "[难过]"
+	}, {
+		"url": "151.gif",
+		alt: "[坏]"
+	}, {
+		"url": "152.gif",
+		alt: "[亲]"
+	}, {
+		"url": "153.gif",
+		alt: "[吓]"
+	}, {
+		"url": "154.gif",
+		alt: "[可怜]"
+	}, {
+		"url": "155.gif",
+		alt: "[刀]"
+	}, {
+		"url": "156.gif",
+		alt: "[水果]"
+	}, {
+		"url": "157.gif",
+		alt: "[酒]"
+	}, {
+		"url": "158.gif",
+		alt: "[篮球]"
+	}, {
+		"url": "159.gif",
+		alt: "[乒乓]"
+	}, {
+		"url": "160.gif",
+		alt: "[咖啡]"
+	}, {
+		"url": "161.gif",
+		alt: "[美食]"
+	}, {
+		"url": "162.gif",
+		alt: "[动物]"
+	}, {
+		"url": "163.gif",
+		alt: "[鲜花]"
+	}, {
+		"url": "164.gif",
+		alt: "[枯]"
+	}, {
+		"url": "165.gif",
+		alt: "[唇]"
+	}, {
+		"url": "166.gif",
+		alt: "[爱]"
+	}, {
+		"url": "167.gif",
+		alt: "[分手]"
+	}, {
+		"url": "168.gif",
+		alt: "[生日]"
+	}, {
+		"url": "169.gif",
+		alt: "[电]"
+	}, {
+		"url": "170.gif",
+		alt: "[炸弹]"
+	}, {
+		"url": "171.gif",
+		alt: "[刀子]"
+	}],
+	[{
+		"url": "172.gif",
+		alt: "[足球]"
+	}, {
+		"url": "173.gif",
+		alt: "[瓢虫]"
+	}, {
+		"url": "174.gif",
+		alt: "[翔]"
+	}, {
+		"url": "175.gif",
+		alt: "[月亮]"
+	}, {
+		"url": "176.gif",
+		alt: "[太阳]"
+	}, {
+		"url": "177.gif",
+		alt: "[礼物]"
+	}, {
+		"url": "178.gif",
+		alt: "[抱抱]"
+	}, {
+		"url": "179.gif",
+		alt: "[拇指]"
+	}, {
+		"url": "180.gif",
+		alt: "[贬低]"
+	}, {
+		"url": "181.gif",
+		alt: "[握手]"
+	}, {
+		"url": "182.gif",
+		alt: "[剪刀手]"
+	}, {
+		"url": "183.gif",
+		alt: "[抱拳]"
+	}, {
+		"url": "184.gif",
+		alt: "[勾引]"
+	}, {
+		"url": "185.gif",
+		alt: "[拳头]"
+	}, {
+		"url": "186.gif",
+		alt: "[小拇指]"
+	}, {
+		"url": "187.gif",
+		alt: "[拇指八]"
+	}, {
+		"url": "188.gif",
+		alt: "[食指]"
+	}, {
+		"url": "189.gif",
+		alt: "[ok]"
+	}, {
+		"url": "190.gif",
+		alt: "[情侣]"
+	}, {
+		"url": "191.gif",
+		alt: "[爱心]"
+	}, {
+		"url": "192.gif",
+		alt: "[蹦哒]"
+	}, {
+		"url": "193.gif",
+		alt: "[颤抖]"
+	}, {
+		"url": "194.gif",
+		alt: "[怄气]"
+	}, {
+		"url": "195.gif",
+		alt: "[跳舞]"
+	}],
+	[{
+		"url": "196.gif",
+		alt: "[发呆]"
+	}, {
+		"url": "197.gif",
+		alt: "[背着]"
+	}, {
+		"url": "198.gif",
+		alt: "[伸手]"
+	}, {
+		"url": "199.gif",
+		alt: "[耍帅]"
+	}, {
+		"url": "200.png",
+		alt: "[微笑]"
+	}, {
+		"url": "201.png",
+		alt: "[生病]"
+	}, {
+		"url": "202.png",
+		alt: "[哭泣]"
+	}, {
+		"url": "203.png",
+		alt: "[吐舌]"
+	}, {
+		"url": "204.png",
+		alt: "[迷糊]"
+	}, {
+		"url": "205.png",
+		alt: "[瞪眼]"
+	}, {
+		"url": "206.png",
+		alt: "[恐怖]"
+	}, {
+		"url": "207.png",
+		alt: "[忧愁]"
+	}, {
+		"url": "208.png",
+		alt: "[眨眉]"
+	}, {
+		"url": "209.png",
+		alt: "[闭眼]"
+	}, {
+		"url": "210.png",
+		alt: "[鄙视]"
+	}, {
+		"url": "211.png",
+		alt: "[阴暗]"
+	}, {
+		"url": "212.png",
+		alt: "[小鬼]"
+	}, {
+		"url": "213.png",
+		alt: "[礼物]"
+	}, {
+		"url": "214.png",
+		alt: "[拜佛]"
+	}, {
+		"url": "215.png",
+		alt: "[力量]"
+	}, {
+		"url": "216.png",
+		alt: "[金钱]"
+	}, {
+		"url": "217.png",
+		alt: "[蛋糕]"
+	}, {
+		"url": "218.png",
+		alt: "[彩带]"
+	}, {
+		"url": "219.png",
+		alt: "[礼物]"
+	}, ]
+]
+
+/**@dateTimeFliter 转换格林日期时间格式为常用日期格式
+ * @time[必填] 						Date  		格林日期格式
+ * @part[可选,默认:0]				Number      选择返回日期时间部分  列:0:返回所有 1:只返回日期  2:只返回时间
+ * @dateComplete[可选,默认:true] 	Boolean 	日期位数不足是否添0补齐:true:补齐,false:不补齐
+ * @timeComplete[可选,默认:true] 	Boolean 	时间位数不足是否添0补齐:true:补齐,false:不补齐
+ * @dateConnector[可选,默认:-] 		String 		年月日连接符  例: - : /
+ * @timeConnector[可选,默认::] 		String 		时间连接符   例: - : /
+ * @hour12[可选,默认:false]          Boolean     是否返回12小时制时间   例: true:返回12小时制时间   false:返回24小时制时间
+ * @return   '2019-11-25 15:05:54'  String    返回示例
+ * **/
+commen.dateTimeFliter = function(time, part = 0, dateComplete = true, timeComplete = true, dateConnector = '-',
+	timeConnector = ':', hour12 = false) {
+	let year = time.getFullYear()
+	let month = time.getMonth() + 1
+	let day = time.getDate()
+	let hour = time.getHours()
+	let minute = time.getMinutes()
+	let second = time.getSeconds()
+	let dateStr = ''
+	let timeStr = ''
+	//转换日期
+	if (dateComplete) { //添0补齐
+		if (month < 10) {
+			month = '0' + month
+		}
+		if (day < 10) {
+			day = '0' + day
+		}
+	}
+	dateStr = year + dateConnector + month + dateConnector + day
+	//转换时间
+	//修改小时制
+	if (hour12) {
+		if (hour > 12) {
+			hour = hour - 12
+			if (timeComplete) {
+				if (hour < 10) {
+					hour = '下午 ' + '0' + hour
+				} else {
+					hour = '下午 ' + hour
+				}
+			}
+		} else {
+			if (timeComplete) {
+				if (hour < 10) {
+					hour = '上午 ' + '0' + hour
+				} else {
+					hour = '上午 ' + hour
+				}
+			}
+		}
+	}
+	//判断分钟与秒
+	if (timeComplete) { //添0补齐
+		if (minute < 10) {
+			minute = '0' + minute
+		}
+		if (second < 10) {
+			second = '0' + second
+		}
+	}
+	timeStr = hour + timeConnector + minute + timeConnector + second
+	//合成输出值
+	if (part == 0) {
+		return dateStr + ' ' + timeStr
+	} else if (part == 1) {
+		return dateStr
+	} else if (part == 2) {
+		return timeStr
+	}
+	return '传参有误'
+}
+
+
+
+export default commen

+ 44 - 0
config/tim/tim.js

@@ -0,0 +1,44 @@
+import TIM from 'tim-js-sdk'
+
+// 发送图片、文件等消息需要的 COS SDK
+import COS from "cos-js-sdk-v5"
+
+import config from '../config.js'
+
+let options = {
+	SDKAppID: config.sdkAppId // 即时通信应用的 SDKAppID
+};
+// 创建 SDK 实例,TIM.create() 方法对于同一个 SDKAppID 只会返回同一份实例
+const tim = TIM.create(options); // SDK 实例通常用 tim 表示
+
+const TIMData = TIM
+
+// 注册 COS SDK 插件
+tim.registerPlugin({
+	'cos-js-sdk': COS
+});
+
+function genTestUserSig(userID) {
+	const SDKAPPID = config.sdkAppId;
+	const EXPIRETIME = 604800;
+	const SECRETKEY = config.secretKey;
+
+	if (SDKAPPID === '' || SECRETKEY === '') {
+		alert(
+			'请先配置好您的账号信息: SDKAPPID 及 SECRETKEY ' +
+			'\r\n\r\nPlease configure your SDKAPPID/SECRETKEY in js/debug/GenerateTestUserSig.js'
+		);
+	}
+	const generator = new LibGenerateTestUserSig(SDKAPPID, SECRETKEY, EXPIRETIME);
+	const userSig = generator.genTestUserSig(userID);
+	return {
+		sdkAppId: SDKAPPID,
+		userSig: userSig
+	};
+}
+
+export default {
+	tim,
+	TIMData,
+	genTestUserSig
+}

+ 15 - 0
config/tim/trtc-calling.js

@@ -0,0 +1,15 @@
+import { tim } from './tim'
+import TRTCCalling from 'trtc-calling-js'
+import config from '../config.js'
+
+let options = {
+  SDKAppID: config.sdkAppId,  // 接入时需要将0替换为您的云通信应用的 SDKAppID
+  tim: tim,
+}
+
+const trtcCalling = new TRTCCalling(options)
+
+// 4 无日志级别
+trtcCalling.setLogLevel(0)
+
+export default trtcCalling

+ 24 - 0
config/tim/user.js

@@ -0,0 +1,24 @@
+const userList = [{
+		user: '1',
+		userId: '1',
+		userSig: 'eJwtzMEKgkAUheF3mXXIzL2OqdAirBA00JJcDzrWpZJh0hCid8-U5fkO-B9WpGfnrS0LGTicraZNtW47amhiseCrvitjqGahcDmXASLC-OjBkNWjSymBcz5rR8*-ebj2UXjSXyp0HZsxdP0jM5kbH9u8vF1OA5ZWwT4v8iTq1aFJq12UYALBdsO*PwqyLwM_',
+		img: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1735490596,2760195857&fm=26&gp=0.jpg'
+	},
+	{
+		user: '2',
+		userId: '2',
+		userSig: 'eJyrVgrxCdYrSy1SslIy0jNQ0gHzM1NS80oy0zIhwlDB4pTsxIKCzBQlK0MTAwNTS2NjYyOITGpFQWZRKlDc1NTUyMDAACJakpkLEjMzNrcwNjS3sICakpkONLM0uCgoJ0a-JD-b2Cc8OzLLyCdSOz-RP7DYqcgo2MXfzNvI3M8tM9PfWzss2VapFgBByi*R',
+		img: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1735490596,2760195857&fm=26&gp=0.jpg'
+	},
+	{
+		user: '3',
+		userId: '3',
+		userSig: 'eJyrVgrxCdYrSy1SslIy0jNQ0gHzM1NS80oy0zLBwsZQweKU7MSCgswUJStDEwMDU0tjY2MjiExqRUFmUSpQ3NTU1MjAwAAiWpKZCxIzMza3MDY0MjGFmpKZDjSzNLEoMdzbzDQ4I83ZPSuiyCjIN88zxaIszTwrPNTZKCTVNbQ0WdspP9fV0VapFgAPEi*D',
+		img: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1735490596,2760195857&fm=26&gp=0.jpg'
+	}
+]
+
+
+
+
+export default userList

+ 14 - 0
index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>

+ 44 - 0
main.js

@@ -0,0 +1,44 @@
+import App from './App'
+
+// #ifndef VUE3
+import Vue from 'vue'
+import uView from 'uview-ui'
+import store from './store/index.js'
+import tim from './config/tim/tim.js'
+import TIM from 'tim-js-sdk'
+import commen from './config/tim/commen.js'
+import format from './utils/format.js'
+import config from './config/config.js'
+import trtcCalling from './config/tim/trtc-calling.js'
+import TRTCCalling from 'trtc-calling-js'
+
+Vue.use(uView)
+
+Vue.prototype.config = config
+Vue.prototype.$store = store
+Vue.prototype.tim = tim.tim	// tim sdk 引入后生成的tim服务
+Vue.prototype.$TIM = TIM
+Vue.prototype.$commen = commen
+Vue.prototype.$format = format
+Vue.prototype.trtcCalling = trtcCalling
+Vue.prototype.TRTCCalling = TRTCCalling
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+const app = new Vue({
+	...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import {
+	createSSRApp
+} from 'vue'
+export function createApp() {
+	const app = createSSRApp(App)
+	return {
+		app
+	}
+}
+// #endif

+ 75 - 0
manifest.json

@@ -0,0 +1,75 @@
+{
+	"name": "即时通讯",
+	"appid": "__UNI__021883E",
+	"description": "用于退役军人即时通讯使用",
+	"versionName": "1.0.0",
+	"versionCode": "100",
+	"transformPx": false,
+	/* 5+App特有相关 */
+	"app-plus": {
+		"usingComponents": true,
+		"nvueStyleCompiler": "uni-app",
+		"compilerVersion": 3,
+		"splashscreen": {
+			"alwaysShowBeforeRender": true,
+			"waiting": true,
+			"autoclose": true,
+			"delay": 0
+		},
+		/* 模块配置 */
+		"modules": {},
+		/* 应用发布信息 */
+		"distribute": {
+			/* android打包配置 */
+			"android": {
+				"permissions": [
+					"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+					"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+					"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+					"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CAMERA\"/>",
+					"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+					"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+					"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+					"<uses-feature android:name=\"android.hardware.camera\"/>",
+					"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+				]
+			},
+			/* ios打包配置 */
+			"ios": {},
+			/* SDK配置 */
+			"sdkConfigs": {}
+		}
+	},
+	/* 快应用特有相关 */
+	"quickapp": {},
+	/* 小程序特有相关 */
+	"mp-weixin": {
+		"appid": "",
+		"setting": {
+			"urlCheck": false
+		},
+		"usingComponents": true
+	},
+	"mp-alipay": {
+		"usingComponents": true
+	},
+	"mp-baidu": {
+		"usingComponents": true
+	},
+	"mp-toutiao": {
+		"usingComponents": true
+	},
+	"uniStatistics": {
+		"enable": false
+	},
+	"vueVersion": "2",
+	"h5": {
+		"template": ""
+	}
+}

+ 55 - 0
node_modules/cos-js-sdk-v5/.github/workflows/auto-changelog.yml

@@ -0,0 +1,55 @@
+name: ChangeLog
+
+on:
+  workflow_dispatch:
+  release:
+    types: [published]
+
+jobs:
+  build:
+
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/setup-node@v2-beta
+      with:
+        node-version: '12'
+    - uses: actions/checkout@v2
+      with:
+        fetch-depth: 0 
+    
+    - name: Checkout Tool
+      uses: actions/checkout@v2
+      with:
+        repository: konakonall/auto-changelog
+        path: 'auto-changelog'
+    - name: Build Tool
+      run: |
+        cd auto-changelog
+        npm install
+        npm link
+        
+    - name: Generate ChangeLog
+      env: # Or as an environment variable
+          TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      run: |
+        auto-changelog --token $TOKEN
+    - name: Cat ChangeLog
+      run: cat CHANGELOG.md
+    
+    - name: Commit files
+      env:
+        CI_USER: "gouki0123"
+        CI_EMAIL: "gouki0123@gmail.com"
+      run: |
+        git config --local user.email "$CI_EMAIL"
+        git config --local user.name "$CI_USER"
+        git add CHANGELOG.md && git commit -m 'Updated CHANGELOG.md' && echo "push=1" >> $GITHUB_ENV || echo "No changes to CHANGELOG.md"
+
+    - name: Push changes
+      if: env.push == 1
+      env:
+        CI_USER: "gouki0123"
+        CI_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      run: |
+        git push "https://$CI_USER:$CI_TOKEN@github.com/$GITHUB_REPOSITORY.git" HEAD:master

+ 893 - 0
node_modules/cos-js-sdk-v5/CHANGELOG.md

@@ -0,0 +1,893 @@
+# Changelog
+
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
+
+## [v1.2.21](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.20...v1.2.21) - 2021-11-11
+
+fix:修复getBucketReferer已知错误
+
+### Merged
+
+- fix:修复getObjectUrl bug [`#128`](https://github.com/tencentyun/cos-js-sdk-v5/pull/128)
+
+### Commits
+
+- fix:修复getBucketReferer已知错误 [`c482be3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c482be32f42f3864af4aa5717e9e9506cd6fcd4d)
+
+## [v1.2.20](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.19...v1.2.20) - 2021-10-27
+
+fix:修复getObjectUrl报错问题
+
+### Commits
+
+- fix:修复getObjectUrl bug [`c0a60f8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c0a60f89e8dbc872e24c7cce0a319242e51a3ec7)
+- update d.ts [`e38f6cb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e38f6cb3e3a22e0df986441adbe348e7417ca7e4)
+- upd:d.ts补充Range、ChunkSize类型说明 [`7167c35`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7167c35bbc2af9a56eb6862b094b67250a3b8826)
+
+## [v1.2.19](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.18...v1.2.19) - 2021-09-02
+
+### Commits
+
+- support opt.xhrFields [`6e58452`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6e58452c12c2e920148929b2d2b8e2de1963f896)
+
+## [v1.2.18](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.17...v1.2.18) - 2021-09-01
+
+### Commits
+
+- support x-cos-mime-limit [`737e698`](https://github.com/tencentyun/cos-js-sdk-v5/commit/737e6989a5fc34bb5c4084b2ac99f433c2b80ac9)
+- 支持已设置 Domain 时,不传 Bucket Region [`0a9438b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0a9438beb0309062542ef6818fb6b0e71d059b84)
+- 去掉调试代码 [`ff27d82`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ff27d828c4709192d4495261646a140b3fa9b962)
+
+## [v1.2.17](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.16...v1.2.17) - 2021-08-30
+
+### Commits
+
+- add after-receive [`72f4a24`](https://github.com/tencentyun/cos-js-sdk-v5/commit/72f4a24d48f3c9c5ae056b4d6d44c1a32791464c)
+- reset sts.js [`63ce64f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/63ce64fc98b4694927d2ac18ba8d09457751361e)
+
+## [v1.2.16](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.15...v1.2.16) - 2021-08-04
+
+### Merged
+
+- upd:补充index.d.ts QueryString [`#119`](https://github.com/tencentyun/cos-js-sdk-v5/pull/119)
+- feat:补充vueDemo [`#116`](https://github.com/tencentyun/cos-js-sdk-v5/pull/116)
+
+### Commits
+
+- support Timeout [`552566d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/552566da070b72bba5615cda1f56d086bddde56c)
+- Updated CHANGELOG.md [`3ebbdc9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3ebbdc9ae5780f60801f2d4a255519a83ba3afe9)
+- Update demo.js [`e154082`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e154082a52591650a0fa5b57c655d68fa375f111)
+
+## [v1.2.15](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.14...v1.2.15) - 2021-07-01
+
+- 分块上传upload part支持headers白名单
+- getObjectUrl 支持Query、Headers参数
+
+### Merged
+
+- feat:uploadPart新增headers白名单 [`#114`](https://github.com/tencentyun/cos-js-sdk-v5/pull/114)
+
+### Commits
+
+- Updated CHANGELOG.md [`ca19ef2`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ca19ef2652a9d88486b564e24a65f7ab5cd0034e)
+- feat:getObjectUrl支持Headers Query参数 [`62c6dd7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/62c6dd7fa436dee30a82be6c5703d377ab31549e)
+
+## [v1.2.14](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.13...v1.2.14) - 2021-06-21
+
+### Merged
+
+- feat:兼容ie promise [`#113`](https://github.com/tencentyun/cos-js-sdk-v5/pull/113)
+
+### Commits
+
+- Updated CHANGELOG.md [`c804b41`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c804b41adc65b344cb39cc6edd6554a67050c1ec)
+
+## [v1.2.13](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.12...v1.2.13) - 2021-06-11
+
+- 新增高级上传接口
+
+### Merged
+
+- Feat/add upload file [`#112`](https://github.com/tencentyun/cos-js-sdk-v5/pull/112)
+
+### Commits
+
+- add crc64 demo [`121bf8c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/121bf8c349cc5652804d1e03daeac45d16255c3f)
+- feat:新增高级上传接口,支持单文件上传根据SliceSize自动选择普通上传还是分块上传 [`4414530`](https://github.com/tencentyun/cos-js-sdk-v5/commit/44145301b60a7f6e935db31df59a2497f0d7196e)
+- update version 1.2.13 [`ebe25a4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ebe25a4515ec28bcad2f7376a1ed7b0205266f27)
+- upd:补充index.d.ts [`6d5999f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6d5999f0a26504543f68f089217b1d1394e3e16f)
+- Updated CHANGELOG.md [`3cd641a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3cd641acdd41ad1033e8e822b66101b069392d75)
+- upd:修改index.d.ts [`cf7eda1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cf7eda1d08c62d99bf29cedec35465f98af63857)
+
+## [v1.2.12](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.11...v1.2.12) - 2021-06-04
+
+-demo新增简单上传base64内容文件
+-sliceUploadFile方法新增返回值UploadId
+
+### Merged
+
+- Feat/put object base64&return upload [`#111`](https://github.com/tencentyun/cos-js-sdk-v5/pull/111)
+
+### Commits
+
+- feat [`1e2ca3a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1e2ca3ae255f64fee4aaab36c01d5a03eb3162a2)
+- upd:sliceUploadFile返回UploadId [`54d100f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/54d100f41c8bd124c978860532d8a2a81ab1ff9d)
+- Updated CHANGELOG.md [`4a04539`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4a0453966d67b586dbfe186e38973f72ffa8f9bd)
+- update version 1.2.12 [`843ffba`](https://github.com/tencentyun/cos-js-sdk-v5/commit/843ffba1ed4bb22ed5b23e5aeb7833f17f5577ad)
+- update version 1.2.12 [`cd0be19`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cd0be1996ee5bf9e1cd007da2f44b121f23c04ab)
+- upd:sliceUploadFile返回UploadId [`4ff8a8e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4ff8a8ef35e5e6e80ed6aa2fdac629a954e596d6)
+- upd:优化base64文件上传demo [`cb8f356`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cb8f356b2774280d7dce7886f4016a84c724fa14)
+- _No commit message_ [`c20924e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c20924e01e53e2045c2e30e76449a3d38dba6d57)
+
+## [v1.2.11](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.10...v1.2.11) - 2021-05-28
+
+### Merged
+
+- Feat/env warning [`#109`](https://github.com/tencentyun/cos-js-sdk-v5/pull/109)
+- feat:新增sdk运行环境错误提示 [`#108`](https://github.com/tencentyun/cos-js-sdk-v5/pull/108)
+
+### Commits
+
+- update version 1.2.11 [`1a1ec58`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1a1ec58f1b1721f7a60d201fa0b63ea071836b66)
+- Updated CHANGELOG.md [`f4bd1fb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f4bd1fbc2a9f47d19b7b3793e9693b6f73647b96)
+- update demo [`7d711c1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7d711c1f2fa1eae1affd8c452020cc93b024c809)
+- upd:sdk运行环境错误提示文案修改 [`a6fbd71`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a6fbd71751f67074cfad619141978d4037547ce9)
+- upd:sdk运行环境错误提示文案修改 [`0a854fd`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0a854fd01ff54b0b7b8523c4a615d528f8ffeb41)
+- Update package.json [`4b09275`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4b09275728622de73181b64ae626d13965c34f69)
+- update demo [`a981cc8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a981cc823253d2eec6fe92903599479a107b5f5f)
+
+## [v1.2.10](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.9...v1.2.10) - 2021-05-10
+
+### Merged
+
+- feat: 修改 demo 表现形式,增加数据万象 demo [`#106`](https://github.com/tencentyun/cos-js-sdk-v5/pull/106)
+- feat: 增加支持全球加速配置及图片处理。 [`#105`](https://github.com/tencentyun/cos-js-sdk-v5/pull/105)
+- Fix/v1.2.9 [`#104`](https://github.com/tencentyun/cos-js-sdk-v5/pull/104)
+
+### Commits
+
+- fix: 优化 demo.js [`bce7d0e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/bce7d0e26b91bee4deb8968c789df3ef0bcef3e9)
+- fix: getAuthorization 出错时能把日志打印在输入框中 [`7e823bb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7e823bbaf631e3e7002bddc519c4989f7f7307eb)
+- fix: 修改 text 为 header [`9085656`](https://github.com/tencentyun/cos-js-sdk-v5/commit/90856563dbb14e7132ff880c27124aff8e6e62b4)
+- fix: 修复 getAuth 里代码逻辑报错 [`b0f12c1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b0f12c1b5f2dd7756af2de4ec1e9501dbcfc1301)
+
+## [v1.2.9](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.8...v1.2.9) - 2021-04-15
+
+### Commits
+
+- 增加 Location 返回值 [`6a57ed0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6a57ed0ad191193841dbf0f706f465e5f96ecfa3)
+- 优化 Demo [`4ca7188`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4ca7188d13cd12d99965d86cfb6d4f31e84f942d)
+- 优化 Demo [`f07d85c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f07d85c94a0c28cd9dcd3cfa022263ce6c307300)
+
+## [v1.2.8](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.7...v1.2.8) - 2021-03-17
+
+### Commits
+
+- 提供公共的 cos.request 方法 [`3c0bc2c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3c0bc2c8a39c342fa47ffb4fbd5703eddd3c7229)
+
+## [v1.2.7](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.6...v1.2.7) - 2021-03-12
+
+### Commits
+
+- 修复判断签名格式报错 [`069754c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/069754c8e389372d165169700c7f884d5abfda17)
+
+## [v1.2.6](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.5...v1.2.6) - 2021-03-10
+
+### Commits
+
+- 增加分片上传取消例子 [`a5b2c51`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a5b2c5120b140e16df6b8d6086aa163fd7bb39ca)
+- Content-Type 不参与签名 [`e79acf9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e79acf9d49d66c33da5b30879dd05a8358f6144f)
+
+## [v1.2.5](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.4...v1.2.5) - 2021-03-04
+
+### Commits
+
+- add BucketEncryption APIS [`a16493c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a16493ca7ea87cc701ab296ccbabd617c75da307)
+- add BucketEncryption APIS [`bbf407f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/bbf407f803eca3840c78702f6b84ba0bcf2f0641)
+
+## [v1.2.4](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.3...v1.2.4) - 2021-02-26
+
+### Commits
+
+- v1.2.4 例子里 XCosSecurityToken 改为 SecurityToken [`dda5aa8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/dda5aa8984c55d72559bbdff545e48e6f15757b4)
+- Updated CHANGELOG.md [`ac3c7df`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ac3c7df3ca5fa4f9ddd59ab0a7c8c239f8ed0870)
+
+## [v1.2.3](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.1...v1.2.3) - 2021-02-24
+
+### Commits
+
+- v1.2.3 fix base64 error [`c0c1696`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c0c16964154caec248bd742083fe1ac4db261a39)
+- Updated CHANGELOG.md [`691c09f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/691c09fdc4473ba99cde39af09439e2aceb79b85)
+- 修改接口描述 [`67c842d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/67c842d8707e38a37b1c0e42c49df9acd3ae8779)
+
+## [v1.2.1](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.2.0...v1.2.1) - 2021-02-05
+
+* 修复 md5 计算报错
+
+### Commits
+
+- 修复 md5 计算报错 [`888f50f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/888f50f24f279e600eb4413033046d5f4c7201c9)
+- 修改用例顺序 [`fc42ef3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fc42ef350a1cc14ef0a76153f1ada0bf5b2bc87e)
+- Updated CHANGELOG.md [`743a7d3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/743a7d33b45ebaa72e9c5f9e809d5c5c8ca97498)
+- 修改 md5 测试用例 [`52403b8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/52403b81295a1255b94f0440071bd017ec7c5f8c)
+
+## [v1.2.0](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.10...v1.2.0) - 2021-02-03
+
+* 整改错误格式
+* 补充测试用例
+* 增加覆盖率统计
+* 增加 d.ts 支持
+* 优化签名计算逻辑
+* getObject 接口支持 onProgress
+* 修复 global 报错
+
+### Commits
+
+- 规范错误格式 [`23a1efd`](https://github.com/tencentyun/cos-js-sdk-v5/commit/23a1efd4deb914fdb8a63bbec416609cb877c9fa)
+- 补充测试用例 [`c4dbcc7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c4dbcc735036cead50d3d09e4a1aed324487096f)
+- 补充测试用例 [`1991c3f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1991c3f50a2339331cb4a76c0ba33136146c9709)
+- 增加测试用例覆盖率统计 [`dbf44a4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/dbf44a4ee3f409dad0f3eca9f4c7098763eb6486)
+- 提示错误字段建议 [`34d9bc6`](https://github.com/tencentyun/cos-js-sdk-v5/commit/34d9bc6d918a045712f2d68776d03de058214f59)
+- 增加 nyc 依赖 [`6e61937`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6e6193790660b713e5741902ac9f4652b676541b)
+
+## [v1.1.10](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.9...v1.1.10) - 2021-01-25
+
+### Commits
+
+- 优化 d.ts 问题 [`8b30286`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8b30286c6cc0f3ab88ba460982d41a04f2fef37b)
+- 优化 d.ts 问题 [`92c4ae1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/92c4ae10858e53d17dd5a947ef1874e8af3b162a)
+
+## [v1.1.9](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.8...v1.1.9) - 2021-01-18
+
+### Commits
+
+- 修复 global 报错 [`1dbfefc`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1dbfefca6cd8e3ecdcb5a87dbe91fa51c7e9f3c0)
+
+## [v1.1.8](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.7...v1.1.8) - 2021-01-14
+
+### Commits
+
+- complete 接口 xml body 去掉空格 [`9dfa8be`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9dfa8be87a700e4c5accdf3b2265695813182df6)
+
+## [v1.1.7](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.6...v1.1.7) - 2021-01-13
+
+### Commits
+
+- 增加 index.d.ts 声明文件 [`1fe6e95`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1fe6e9590bb48e95f35e8030789c9dc3bc9d3446)
+
+## [v1.1.6](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.5...v1.1.6) - 2021-01-12
+
+### Commits
+
+- getObject 支持 onProgress [`b31690d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b31690d3ecf0ed072808ca0643a888379e90ee5c)
+- Updated CHANGELOG.md [`7869965`](https://github.com/tencentyun/cos-js-sdk-v5/commit/78699653328c775a20dabe1483871eb815ad46e1)
+- Update start.md [`00fb9f1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/00fb9f1ac59c88f130c9ac377e02d32ee727be3d)
+- 修改签名错误 [`7152fde`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7152fdee767158b946bf1896851ec44f7eb8b720)
+
+## [v1.1.5](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.3...v1.1.5) - 2020-12-17
+
+分片支持 Pic-Operations 参数,和 UploadResult 返回值
+
+### Commits
+
+- putObject sliceUploadFile 统一返回值格式。 [`f95505c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f95505ca389cd7a7b92b39d3fb1873eb71af27dd)
+- putObject sliceUploadFile 统一返回值格式。 [`056bbb5`](https://github.com/tencentyun/cos-js-sdk-v5/commit/056bbb5fcd54d7c4d9f574879d96176be6f2fda6)
+- 修复分片上传传了 Pic-Operations 参数后,保存的 fileid 图片 Content-Type 不对的问题。 [`ee44e5f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ee44e5f7f3baf3fb23bcc0c286f6bca9756459ba)
+- Updated CHANGELOG.md [`da2e8ae`](https://github.com/tencentyun/cos-js-sdk-v5/commit/da2e8aebdb1dca0f9eeca19290861dd968ebd032)
+- v1.1.5 multipartComplete 接口默认 Content-Type: application/xml [`3b3f5cb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3b3f5cbe8d526252d495f58ea2a31e1c25402c1c)
+- 改正 Location 格式 [`7f82db2`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7f82db218a2d6389338e4530a57cb1f3ac475cb5)
+
+## [v1.1.3](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.2...v1.1.3) - 2020-12-16
+
+sliceuploadFile 接口支持 Pic-Operations 传递给 multipartComplete 接口
+
+### Commits
+
+- 增加示例 [`26a1063`](https://github.com/tencentyun/cos-js-sdk-v5/commit/26a1063aa1a6ee4c8adc9137c874cf1e5bb34dee)
+- Updated CHANGELOG.md [`7878866`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7878866e025b9578eb9fbedbfd09bb6e1d3013df)
+- 分片上传支持 pic-operations 传递给 complete 接口 [`4c46823`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4c468232273808775a193e3b5c7b346d0a6fb280)
+- 修改用例 [`091cbd4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/091cbd4fda7d4967da74e853ecdf7840173cf24a)
+- Update watcher.js [`9f2be01`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9f2be019d559b61164521d5ef54aceca2553dca7)
+- 加日志 [`a1932b4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a1932b464b8f0c8b963d3e76cd2c0b23dea31b30)
+- 修改用例 [`3ff5e29`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3ff5e29390aa0e7b5aece093ad9b3023c846582e)
+
+## [v1.1.2](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.1...v1.1.2) - 2020-12-02
+
+* 优化万象数据,增加 Query 参数,putObject 支持获取返回值。
+* sliceuploadFile 接口支持 x-cos-meta 传递给 multipartComplete 接口
+
+### Commits
+
+- 分片上传支持 x-cos-meta 传递给 complete 接口 [`893dde3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/893dde395fa5d8286e1685d5778caf99ecc0a0bc)
+
+## [v1.1.1](https://github.com/tencentyun/cos-js-sdk-v5/compare/v1.1.0...v1.1.1) - 2020-12-02
+
+### Commits
+
+- Updated CHANGELOG.md [`5315fe5`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5315fe5951aa0adb54743bc842866d4e454e5008)
+- add auto chagelog workflow [`55b529a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/55b529a621188542523bade3ad72c82e08d16467)
+- 支持 Query/CI [`e38e060`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e38e06073d87a30166ffb56ec6cb8d62b6468967)
+- 支持 Query/CI [`7c4f61b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7c4f61b8596657fde9d8d69c76cbcb41e63f45a9)
+- 支持 Query/CI [`91dcd0e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/91dcd0e605e9d73fb5d4917daed902c08f3d5a22)
+
+## [v1.1.0](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.22...v1.1.0) - 2020-11-19
+
+### Merged
+
+- Update test.yml [`#91`](https://github.com/tencentyun/cos-js-sdk-v5/pull/91)
+- Create test.yml [`#90`](https://github.com/tencentyun/cos-js-sdk-v5/pull/90)
+- add puppeteer watcher for QUnit test. [`#89`](https://github.com/tencentyun/cos-js-sdk-v5/pull/89)
+- Update README.md [`#77`](https://github.com/tencentyun/cos-js-sdk-v5/pull/77)
+
+### Commits
+
+- v0.5.25 修复 AccessControlList 报错 [`8bf50c0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8bf50c032dca678b0ef3afc76d47d3825dff0070)
+- v0.5.24 修复 Grant 报错 [`8653104`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8653104bd874ac4af3cd788349c3afd6a1d8d056)
+- v1.0.1 请求库 jquery 改为直接 ajax [`a451041`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a4510414ce6edb55643847af5bda260e248837b5)
+- 增加 BucketReferer/BucketDomain/BucketOrigin/BucketLogging/BucketInventory/BucketAccelerate/ObjectTagging 接口 [`092a33b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/092a33b06610c63023b8572f97e17dd418293d32)
+- update uploadId cache [`47037d0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/47037d02ca7fd94035a13d21aead6d85a3719bbb)
+- 更换 md5 库,加快 md5 计算速度 [`122d069`](https://github.com/tencentyun/cos-js-sdk-v5/commit/122d06955e56674201fa54165711e0632d98c34f)
+- v0.5.27 fix md5.js 报毒 [`9988c08`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9988c08e739a703abebea2431c2f98e70863c9b3)
+- 支持 Promise 和 async/await 格式 [`4eee462`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4eee462eb31cf4cf641bc2b326b28f133d92b5d9)
+- 优化代码 [`ca59b26`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ca59b266defa31f4f30b1d20a1b6cfc6aaa41be5)
+- v0.5.26 add GetService/PutBucket [`4d78685`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4d7868507f6b4ec1143ad94d4f9e905b7ce6c323)
+- 优化 ETag 获取 [`9d94011`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9d94011f4c4312bea42303e8b7a757cc7309f807)
+- 增加上传文件夹例子 [`16cfea1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/16cfea130c81ab74f6c9aeb4350b3e6e78297dea)
+- 加分片上传 demo [`02a391b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/02a391b18f42e170843130ee3b23b6d758256e95)
+- 支持 after-receive 事件和 Request 参数 [`f3eab19`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f3eab1968e1ce6872f67d93a061b3206f80f82fa)
+- 加服务端决定文件名的 demo [`3213155`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3213155e99f8ef21d504c29fd037b4de62666945)
+- getObject 增加 DataType 参数 [`62cdcb4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/62cdcb43f2831da0e2ae2dc9c088531043bcea1b)
+- 增加 selectObjectContent [`4d93221`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4d9322104f9036af66c1f318485c65739b9603f0)
+- fix for jUnit test. [`47b3367`](https://github.com/tencentyun/cos-js-sdk-v5/commit/47b3367133ff77af489b59d70b140c836ceebe35)
+- 支持stst StartTime 自动修正时间 [`c7ce625`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c7ce6256738408cee77a3a3e5b31b5af0ce816ba)
+- 优化打包结果的注释 [`467e4c0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/467e4c05ab65b079bdff4d53cb4b29bd19208c01)
+
+## [v0.5.22](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.21...v0.5.22) - 2019-11-29
+
+### Commits
+
+- remove querystring [`d43c064`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d43c06495fb44b02df5de5fafcaa4cdb5aa1ce8c)
+
+## [v0.5.21](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.20...v0.5.21) - 2019-11-28
+
+### Commits
+
+- add website api [`c2e5752`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c2e5752b67f15ad6163f8a98b43d45db02484102)
+- 添加 post-policy demo [`719235c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/719235caa8df2d1d459ba05e43767cbbbcb3fff2)
+- 优化上传队列处理,防止栈溢出 [`39f1e8b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/39f1e8be2232c59e40f0fef66bfe226682a0f4a8)
+- 添加 post-policy demo [`0a157bc`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0a157bc4c46c9b88f5c468d83253b31e3550ecc8)
+- 分片复制,去掉一些无用头部 [`4a6ffee`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4a6ffee1fa642c67fa583a665b9cdbffc7b3a774)
+- 优化调试 server [`3286a50`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3286a50a6a33c588796dba8c2a70483ae33e7a3c)
+- 优化 post policy demo [`01c50fa`](https://github.com/tencentyun/cos-js-sdk-v5/commit/01c50fa1de6605a513b640e7eae8fb57b9ebea3e)
+- Update cors.png to v5 [`bf915b7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/bf915b79e234d3bd527b569ee8b6c8a2c8bb7fcb)
+
+## [v0.5.20](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.17...v0.5.20) - 2019-09-11
+
+### Commits
+
+- 特殊处理微信分片上传图片 [`1a71b0c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1a71b0c64eabc7ad91686b94be76d527a542938b)
+- 特殊处理微信分片上传图片 [`746e580`](https://github.com/tencentyun/cos-js-sdk-v5/commit/746e580b9182e1e17def7c0f5299506eafe8d6d1)
+- 上传支持 AddMetaMd5 [`3c291b4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3c291b4b9cc3ad2fbc5c132c9cfcbb8aec2aae6b)
+- 上传支持 AddMetaMd5 [`f4eeea4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f4eeea4c940baec0513074b9ac2dfaede31b7038)
+- 修复 getObject 问题 [`f7fd3e7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f7fd3e71c112e94a8182893f002347449ee092c5)
+- 优化 list-update 事件,加 setTimeout 截流 [`0f010d0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0f010d0d7be395343f0d2612878a4fa5e25573a0)
+- 上传支持 UploadAddMetaMd5 [`98c730b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/98c730b7ff06a5a228732876f94cac45bb4f48ab)
+- README 加上 Start demo [`03f04d7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/03f04d7eee7c0cc1ea0eb587aa1fe439f64145c1)
+- v0.5.20 优化 putObject 返回 Location [`b96322e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b96322eb512ba49ef568d9c63ea6d7d4485320b7)
+- fix webpack require error [`3b37f51`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3b37f5144218d9330a6928b6c5bf2118cd86b769)
+- fix getObject bug [`6c9a10c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6c9a10cf938f9657fc43bb8bede7fb1ced66c5eb)
+- secret use env [`c34bf68`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c34bf6818f911e89b2842f5417ee1dc78ba53f8d)
+- 上传支持 AddMetaMd5 [`cdd1f1f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cdd1f1f3bb34fae789df977ffa66ef52e6ece07b)
+- 修复 BucketLifecycle 接口的参数问题。 [`5489730`](https://github.com/tencentyun/cos-js-sdk-v5/commit/54897307f268699fe8254d3cbb7f448406b38c2d)
+- 修改默认展示的日志长度 [`7d0edcf`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7d0edcf509fd694c0081fa157870603ad2064081)
+- 修改 package.json 文件。 [`0aa6085`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0aa60858807b2498be71e2c41b4efb28a7b3c66b)
+- 修改README文字。 [`0eed45a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0eed45a02f23aa2e944d71ae92208531dec96cb3)
+- Update LICENSE [`ff6b2fd`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ff6b2fd810e350a2aa45ba64945197a9721d094c)
+- Update sts.js [`c1316f6`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c1316f6066603dfc22130c9336694aab7609172e)
+
+## [v0.5.17](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.13...v0.5.17) - 2019-05-27
+
+### Commits
+
+- 修复 clearQueue Bug [`a8e6f08`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a8e6f0809113fa7b844acbaa0cb8e4f61df9354d)
+- fix authorization error [`7e8a406`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7e8a4069fbd485bbe4b92bb0a26b2b80dacc2f65)
+- 修改复制参数、任务增加 _custom 字段 [`00d04fc`](https://github.com/tencentyun/cos-js-sdk-v5/commit/00d04fc0f8d40b56968327d0b93862a2f26b92c8)
+- getObjectUrl add Expires [`fe74e2d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fe74e2df5191d075483d9abb8a18c9426924f28f)
+
+## [v0.5.13](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.12...v0.5.13) - 2019-04-08
+
+### Commits
+
+- 支持 ServerTime 校正时间 [`1e00556`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1e005569b306130b1f0c518b0439665c666dc40a)
+
+## [v0.5.12](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.11...v0.5.12) - 2019-04-03
+
+### Commits
+
+- STS 接口更新为云API v3 [`2112bac`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2112bac12c27a7a4d18b65229bd047d4fbf3fd25)
+- add onTaskStart [`cc8bc75`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cc8bc7596d9ffc274e6e6511ef50a6b8ac6f6d5c)
+
+## [v0.5.11](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.10...v0.5.11) - 2019-03-12
+
+### Commits
+
+- 修改队列清理,修改 userAgent 容错 [`b478fd3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b478fd35d17e5c179ad2b1642247c47d14ec34e6)
+- 修改注释 [`e805e62`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e805e62c53a351297698a5485e4689947596d957)
+
+## [v0.5.10](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.8...v0.5.10) - 2019-03-08
+
+### Commits
+
+- 修复 global 报错 [`c14714b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c14714b51fe7a2c2050a5a9dca68655f55cef860)
+- v0.5.9 修复 getObject 内容会被解析成 xml 问题 [`6c76e75`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6c76e7564fe5b9bb34dc5c3ffbd011900a62c169)
+- 修改 sts.php [`384767e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/384767ed9f1d7a0dc4b27c86bcf6b864957efa84)
+- Update sts.js [`f4feafe`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f4feafe89c4273504842b42038902149d19aac09)
+- Update sts.php [`a85175b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a85175bf57136e2d3c7c8a297f9e4d1a44bcaf86)
+
+## [v0.5.8](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.7...v0.5.8) - 2019-01-17
+
+### Commits
+
+- 修复 chrome 69 分片上传 Content-Type错误,修复 no-cache 问题,优化分片复制带上元数据 [`9db8ccf`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9db8ccf5ef229cc99f6a620fa6ea40e7fe1d2c74)
+- 优化例子指引 [`e30d407`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e30d407d1b4b1cc14691470c3e3be3f2bcd0f523)
+- 优化例子指引 [`4131313`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4131313783c234c29a679564a40df9ae7a665864)
+- 优化例子指引 [`1387d3f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1387d3f73bf1d0dd741f8162925e5c29164646f3)
+- 优化例子 [`e37246e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e37246e5f38132742155280411796b1901e457c6)
+- 优化例子指引 [`1148a9e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1148a9ea1bbc3ca9b3685027ac9e75b0b844a06a)
+
+## [v0.5.7](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.6...v0.5.7) - 2019-01-10
+
+### Commits
+
+- 修复分片上传 Content-Type 有误 [`ef0a02c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ef0a02cc281374163c608c82e4f3cc39b732f837)
+
+## [v0.5.6](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.5...v0.5.6) - 2019-01-07
+
+### Commits
+
+- 修改 demo [`76c6317`](https://github.com/tencentyun/cos-js-sdk-v5/commit/76c6317a26256a7b18697050256dfc7142f26997)
+- 修复 http 页面微信 webview 分片上传出错 [`e2b1058`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e2b1058b658465cbe26962ef54a01883bd430523)
+- 修改 demo [`8cbbb56`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8cbbb565a51a2f29251fa77ceb25d1fae315994f)
+- 修改 demo [`53408a7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/53408a72adea24967fc5712af12a0599d25f2a95)
+- 修改 demo [`0b1680e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0b1680e8db5ec0c4c9a8b5141ce1af90cd348fa5)
+
+## [v0.5.5](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.4...v0.5.5) - 2018-12-26
+
+### Commits
+
+- 微信 PC webview 计算分片 md5 不复制分片 blob [`170da58`](https://github.com/tencentyun/cos-js-sdk-v5/commit/170da585e8767364107b1ea9948c4a709001b224)
+
+## [v0.5.4](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.3...v0.5.4) - 2018-12-26
+
+### Commits
+
+- 签名增加 Pathname 参数,修复微信 PC webview 分片上传 bug [`1c58e74`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1c58e7498fdb170b245eb436e1ec27a09e4e311a)
+- 修改 sts 例子 [`d5525a3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d5525a31aa9e536ddd78acbe7b1ca1762a302b6f)
+- 更新包引用 [`5d51885`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5d5188515841f7fdeb864ed42ea452ae652f153b)
+- 修改 CORS 配置例子 [`d83e117`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d83e117a8e3564f7d0f04ba1f68b0062f6eb4da8)
+
+## [v0.5.3](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.2...v0.5.3) - 2018-12-24
+
+### Commits
+
+- 去掉 splice log [`fe2a8d5`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fe2a8d5ecd01cb766d969afa25c697d1c3495f63)
+- 去掉 splice log [`48d849b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/48d849b6dbbee36d66f916e57dafafd36c3e264a)
+- 支持去掉队列 [`9da3b71`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9da3b712df69adb409e58651ed399655af7f8add)
+
+## [v0.5.2](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.1...v0.5.2) - 2018-12-21
+
+### Commits
+
+- 支持自动调正浏览器时间偏差 [`d7c8653`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d7c8653cf6eee0e11b66e48de723e1da37b13f77)
+- CORS 例子补充 ExposeHeaders Date [`5b92012`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5b920122170ea6d20f0f5d0902a6da106fca8a74)
+- Key 拼接 url 用 camSafeUrlEncode [`b090acc`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b090acc1f1e7179f385332e4d9994b48b6b62c09)
+- 去掉预埋逻辑 [`1d05f7a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1d05f7ad080eed9cdd48b742233acdf2946143a6)
+
+## [v0.5.1](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.5.0...v0.5.1) - 2018-12-07
+
+### Commits
+
+- Key 拼接 url 用 camSafeUrlEncode [`cf7ca67`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cf7ca67686711e4658c74622fbb9259cc25bac3f)
+
+## [v0.5.0](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.27...v0.5.0) - 2018-12-06
+
+* 签名回调新增 Scope 参数,支持细粒度 STS 权限控制
+* 添加前端签名 js demo/common/cos-auth.min.js
+* 增加 timeout 参数
+
+### Commits
+
+- 支持 STS Scope [`e527581`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e527581e0834202c40f4054a65de9160b3e02153)
+- 修改 签名 报错 [`e84677f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e84677f0ccd3bef3798e4d46ecf42ae63cc8d27e)
+
+## [v0.4.27](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.26...v0.4.27) - 2018-11-28
+
+### Commits
+
+- 补充 sts 实例 action 列表 [`174f1de`](https://github.com/tencentyun/cos-js-sdk-v5/commit/174f1deeda0e923d6ffbcc86a751d7b12980264d)
+- 修复 IE bug [`56f405b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/56f405be32e7de92f2c7b06610c8ae2e0ec963c5)
+- update [`cef7929`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cef7929bed0da7c21f0a4c7fcf9a1defe0d3ff85)
+- 去掉调试代码 [`0beb1d3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0beb1d36b5f44cf255b86c4a7dfbc81cd8236029)
+
+## [v0.4.26](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.24...v0.4.26) - 2018-11-22
+
+### Commits
+
+- 去掉两个 sts-auth demo [`d5e6cba`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d5e6cba45294c1a023ec4cf811cff81c5f246810)
+- update simple demo [`7a7e240`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7a7e2406cab312689627606b6ad4ea33cd41fd58)
+- 优化 Body 判断 [`f45024b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f45024bfd80c786d5c1be660b662e3930e460b4c)
+- update demo [`89c77f8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/89c77f8f1ffaf12293c8b69d0b7802398898ef0b)
+- 优化 demo、test [`15e56b5`](https://github.com/tencentyun/cos-js-sdk-v5/commit/15e56b575c0513b3b07f4a697e6802ed0b7e590c)
+- update csp doc [`74db371`](https://github.com/tencentyun/cos-js-sdk-v5/commit/74db371745cfca19766dbbd3eb3eb7e31fdd3bd1)
+- 优化 demo [`77ba2d7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/77ba2d7e58d5071827c22f5928d9924d5ba7ef5c)
+- 兼容 iframe 内上传 iframe 外的 File/Blob [`2ac2cdf`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2ac2cdf62f4608680dc08d7b901de3c31e539bcf)
+- 修改用例 [`b37b0a9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b37b0a9dd6fe33950c068027006c177cf6f320f1)
+- 优化 csp demo [`6422c6a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6422c6a8268e912f3843a5d7205acf46da77c876)
+- Update cos-auth.js [`f481ea2`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f481ea2eea8de85d754869ee62abc4538f366897)
+- 修复 exports 错误 [`1e3b5b2`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1e3b5b2819760873780970820bf5d48f4f77a641)
+- 优化文案 [`bf218ca`](https://github.com/tencentyun/cos-js-sdk-v5/commit/bf218caade2a810b5de8e940de5addc899079868)
+- update demo [`e05f6da`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e05f6da8b3c78f8b76a634b1f7ae00865b16519a)
+
+## [v0.4.24](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.23...v0.4.24) - 2018-11-16
+
+### Commits
+
+- 修改最大分片大小 [`d22de28`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d22de28fddaac6cd091e1ab62fba88bcceebc60c)
+- 修改最大分片大小 [`e8b1b80`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e8b1b80903830824e856ffe8a2be8df34d521c03)
+
+## [v0.4.23](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.20...v0.4.23) - 2018-11-14
+
+* 添加上传队列 demo
+* 添加 UseRawKey 参数,不处理 Key 开头的 /
+* 添加 XCosSecurityToken 参数,支持主动设置 STS token
+* 优化上传流程,修复一些 bug
+* 整理测试用例
+
+### Merged
+
+- 修复Demo里的BUG [`#37`](https://github.com/tencentyun/cos-js-sdk-v5/pull/37)
+
+### Commits
+
+- update csg doc [`52729cb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/52729cb5cd5394661fd289de1dbb343e1f674486)
+- 修改执行流程,支持 UseRawKey 参数,整理用例 [`513a038`](https://github.com/tencentyun/cos-js-sdk-v5/commit/513a0388b40cbced8347b7350047016e719579d5)
+- 上传队列 demo [`e194982`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e194982990764400ab0e70b93d52832f24e90953)
+- update csp doc [`3f8dccd`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3f8dccd22d8cc398ccf78b1abefd416fc7190481)
+- 上传支持 Content-MD5 [`810ef03`](https://github.com/tencentyun/cos-js-sdk-v5/commit/810ef035a275ec8b9ec85b5769decfe590ff3f6d)
+- update csp doc [`cd1ad63`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cd1ad63270244b818aa063a186eeeafb3d91e156)
+- update csp doc [`ac5ae71`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ac5ae713145522411c20695e7d481ea84ffb4b1e)
+- 修改 demo [`4143302`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4143302d27923ff362f3f4c08530ad2d46ed4fed)
+- 实例化支持 XCosSecurityToken 参数 [`cb6870f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cb6870fbe1254f62b4484d46a7eb650d3d5af92a)
+- remove debugger [`e4d3d11`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e4d3d11cddaf4be84177c2c4007fa10afc8c4b5b)
+- 修改 demo [`e25a475`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e25a4756f9d8ff0e75cbc35f663b655c64170de6)
+- update csp doc [`fa8c45b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fa8c45becfea72ffeb404be5992a961101622027)
+- update csp doc [`d107ab1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d107ab1aa8bf9b6a1e77b8f52a8991a7c3454ec1)
+- update csg doc [`eca8124`](https://github.com/tencentyun/cos-js-sdk-v5/commit/eca81243e3bbcf7d770dc8d25bc4fe1c262062d7)
+- Update csp.html [`5fd0e3c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5fd0e3c900b39247fa452e4376d529fa584f5f60)
+- Update api.md [`86c2673`](https://github.com/tencentyun/cos-js-sdk-v5/commit/86c26736495dcf17ff51315c0214edbec182272a)
+- Update start.md [`32ff146`](https://github.com/tencentyun/cos-js-sdk-v5/commit/32ff14661943411d100eac407abdf280222bacbd)
+- bug: fix 403 error [`9a58aa1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9a58aa1cedb242cccb3b7a5e208fd0cc39b660d0)
+- 修复 [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client 的报错 [`1abc9eb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1abc9eb5453a4884e25fa95c17621a303e23bb17)
+- 修改 sts 例子 [`73c3864`](https://github.com/tencentyun/cos-js-sdk-v5/commit/73c3864ef972f6b46adfd5da42cc2d092521f6b9)
+
+## [v0.4.20](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.17...v0.4.20) - 2018-10-18
+
+### Commits
+
+- 修复 getObjectUrl 多一个 sign=xxx [`ce7f326`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ce7f32676dc96266b9097dee156fbddf2f42c6c1)
+- 支持跨区域复制 [`e8a253a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e8a253a71f9760dc58ccb1d1118b3a65eaf17ce3)
+- 修改 demo [`5cd743e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5cd743ec07684adc0a265af7cb7362d6b750ab79)
+- remove debugger [`4051ac9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4051ac96c08e9c033d68e631d670f935baddcc53)
+- 修改 demo [`7984950`](https://github.com/tencentyun/cos-js-sdk-v5/commit/79849509c5864f53d40f18eb11ea90a451c50638)
+- support ForcePathStyle [`e4d43c3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e4d43c3305735d25c2118cd4f11e7e915213aa18)
+
+## [v0.4.17](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.16...v0.4.17) - 2018-09-28
+
+### Commits
+
+- 优化签名提示和 sts 例子 [`7665f7f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7665f7fbffd0e3e709cffe6d8200d3cfda81fcf8)
+- update demo [`e9fd341`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e9fd341cbe27d9c77acfd85b0e593422c87bd620)
+- 增加 deleteBucketPolicy 接口 [`fa00a7f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fa00a7f29a6ec7b42cd8b45a34211e0676f5aeb1)
+
+## [v0.4.16](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.15...v0.4.16) - 2018-09-11
+
+### Commits
+
+- support ForcePathStyle [`3d2ad98`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3d2ad9845d72e9293cfbe74164287dacff90985a)
+
+## [v0.4.15](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.9...v0.4.15) - 2018-09-10
+
+### Commits
+
+- support csp [`d48456c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d48456c8facbbd69d70308bf64468e49df415e8b)
+- 增加 hook 支持 [`d74dc7b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d74dc7ba2bd13f5c883e45cace747a8593dd15b1)
+- 修改 md5 中文字符串错误的问题 [`dcf7ad6`](https://github.com/tencentyun/cos-js-sdk-v5/commit/dcf7ad6eeb1c8a4caf3ef5ebe9a99e08d6acab02)
+- support csp [`1adea99`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1adea99b00c2b75e075ebd4c2b4cf2c8df3dfa74)
+- sliceUploadFile 触发 onProgress [`e373ab7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e373ab7a5f85bb69eea7b832ced2e6f6ce7dd1b7)
+- remove hook and add event 'before-send' [`c560069`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c56006914f1f6078dd3a75bf38cc0d86491fb6a5)
+- update demo [`2a875e8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2a875e873e7ff7e00bd1ee600014e117941d75b1)
+- 0.4.14 增加 kms 加密字段支持 [`b100fb3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b100fb3b36f49d97e48e60836de6b5cd252f9881)
+- 修复复制中文错误 [`291cded`](https://github.com/tencentyun/cos-js-sdk-v5/commit/291cded8f5c535e70df9c47161f8ac8557588db8)
+- 修改 demo [`a05e5c2`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a05e5c2c7fdf45d979893477deb56232371f814e)
+- remove hook and add event 'before-send' [`b06c2f9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b06c2f9af818776f9ca8aaba5cc078e53ee57e79)
+- change demo [`342b268`](https://github.com/tencentyun/cos-js-sdk-v5/commit/342b2689c087af218596f8c98d22ad703229039e)
+- 修改 demo [`8da0c02`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8da0c02c5e4e691ffeed3eb052713793e6c4b426)
+- 修改 sts demo [`ce0df94`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ce0df943c8efac4d12a9a4e9750a02acb965c2bd)
+- 修改临时密钥超时判断时间,60 秒 [`1059949`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1059949c54a54496ab84ecd6c7dcbebc5d4bc32e)
+- fix bug [`f22eb49`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f22eb49a4447f1438bf13aae395c1aacf0269929)
+- 修改复制参数 [`30693e7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/30693e7bac4c816c60a8f086fd140b676aaf31b6)
+- 修改 demo [`2fef2b1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2fef2b14b73c0ce8aed868c3a2535023022fa400)
+- 修改 demo [`eb87c11`](https://github.com/tencentyun/cos-js-sdk-v5/commit/eb87c11c5b11ed23d9a0b85a04d7aba7d4d8bf51)
+- 修改 md5 中文字符串错误的问题 [`688ca30`](https://github.com/tencentyun/cos-js-sdk-v5/commit/688ca30e6896f814d7df47c91103b4a0ed75198e)
+
+## [v0.4.9](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.5...v0.4.9) - 2018-07-16
+
+### Commits
+
+- fix ie11 bug [`0e8c973`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0e8c97333c671264874356ad02314fa9c7318d0e)
+- 增加分片复制功能 sliceCopyFile [`2059860`](https://github.com/tencentyun/cos-js-sdk-v5/commit/20598602eba2c3447e3bde378f3969ce4bf543f4)
+- update [`481fd91`](https://github.com/tencentyun/cos-js-sdk-v5/commit/481fd91187fcbf3c0d23a3ec76643fdfb1a63147)
+- 修复 putObject 返回的 Location 错误 [`9124907`](https://github.com/tencentyun/cos-js-sdk-v5/commit/91249072aa1bedcceb48de5b3ed034b8e3e6d95a)
+- update demo [`60120fa`](https://github.com/tencentyun/cos-js-sdk-v5/commit/60120fa8e08e8ffabd23611625bc8434c9d6f9e1)
+- 增加分片复制,优化代码 [`898c3f8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/898c3f8cfaf43992bd5d997d2badeedf7a401094)
+- build 0.4.9 [`1e6f1af`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1e6f1af055ee3d7c2049b0b073322568ce8d00e7)
+- fix ie11 bug [`8483174`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8483174a7ca4f765b72baf84c3ed50a7419ce273)
+- 修复跨区域复制 bug [`b480f94`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b480f94f82b77cf6f1882c0dddfad8adf0b23d43)
+- 修复 AdGuard 插件导致 Blob 判断出错 [`acccbef`](https://github.com/tencentyun/cos-js-sdk-v5/commit/acccbef74cb94846ef684766d0d5abd59bfc401b)
+- add error doc [`c4faf4a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c4faf4a8fffb7322bca2035a3640891a8d461a4e)
+- add demo [`602d299`](https://github.com/tencentyun/cos-js-sdk-v5/commit/602d29945aed41c0ed3fac694df0bf3656661839)
+- fix copy bug [`c26c0a6`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c26c0a6a2a06d3a14511b270e3b450add212d62a)
+- 修改 demo [`babf47b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/babf47b81dbbe9ebc58977d994c3e7b7bf6a53ae)
+- remove MFADelete [`1405fbe`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1405fbe0165ecfc16ea53c25ab3af92581162c52)
+- Update sts-auth.php [`973c7fe`](https://github.com/tencentyun/cos-js-sdk-v5/commit/973c7fea20550f2eccac30a333c4c798477090e2)
+- Update sts.php [`829d6f3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/829d6f38f762e6ee8c433f805718af2d666e10aa)
+- fix ie11 bug [`53fec6e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/53fec6e84dc54dab120dcbb9ea29c6099db5ee8a)
+- fix ie11 bug [`48169da`](https://github.com/tencentyun/cos-js-sdk-v5/commit/48169da4b0f12784f13fbcebd2862bfb78bb8663)
+
+## [v0.4.5](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.4...v0.4.5) - 2018-05-03
+
+* 修复 sliceUploadFile 方法,所有分片都完成只执行 complete 时,没有反馈进度 100% 的问题
+* 修复 putObject 的 Body 传中文字符串, ContentLength 算错的问题
+* 修复 putObject、sliceUploadFile 参数对象会被 SDK 污染的问题
+* 修复 json2xml 方法在 ie11 的 bug
+* 更正签名例子里 json2str 方法代码冗余
+
+### Commits
+
+- 修改进度反馈 bug,修改参数缺失提示,修改参数对象污染问题 [`fc865b9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fc865b90576a056416b56eb6c05f111b5d6e6f6f)
+- update [`6061f13`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6061f135b84a88168b270d60f1625506e2eabab5)
+- 修改 demo 例子 [`40d1f4b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/40d1f4b928e2bc1613726608e1375f382f48bfa7)
+- 修改 json2str 方法 [`d95cc06`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d95cc06314be0a8814ac914add9a04cb401c1aa1)
+- 增加上传字符串的用例 [`87f758a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/87f758ac86fb1541e6a00da1ae414d85872f2c9c)
+- update [`c71a380`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c71a38079cfa047a2adc48e14a47a910d9b83851)
+- update [`3cda187`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3cda1876e81077fe3a4960de581d28294af8c1b2)
+- 修复 ie11 不兼容问题 [`2695c28`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2695c28aff3ad3c08c012afc0676cbe84796ccd6)
+
+## [v0.4.4](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.3...v0.4.4) - 2018-04-19
+
+* 支持 UploadId 缓存到 LocalStorage,减少 md5 计算过程,加速上传,默认缓存 50 个 UploadId,约占用5KB空间
+* 修改签名 demo,推荐使用临时密钥,更好地在后端控制权限
+
+### Commits
+
+- 支持 UploadId 缓存,修改签名例子 [`e44bad6`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e44bad64198097afb02bb5c211fede4b0999cc3a)
+- cache UploadId [`5495244`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5495244eedad1e577fc9b882876862272efc242a)
+- update demo [`11b942a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/11b942a7259ae4d531f8cce5b12fcdc435d0cbf2)
+- 容错 [`ce3b25e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ce3b25e77a545d1d9ec2b3457d3deb903ff9e488)
+- 修改 auth demo [`fcd6f0a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fcd6f0a442aa8ab4a4ad79324e79cb5063d49e4c)
+- 修改 post demo [`a85e6c4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a85e6c4b415f60e0a8c816ae87964207cd818706)
+
+## [v0.4.3](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.2...v0.4.3) - 2018-04-09
+
+### Commits
+
+- 分片大小参数容错 [`ca65174`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ca65174918992256856b2b50db3ea9fffe3a0610)
+
+## [v0.4.2](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.1...v0.4.2) - 2018-04-08
+
+### Commits
+
+- Update demo.js [`7c32b9e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7c32b9ecaa389f18a1289dc6c657704f00cc7219)
+- 修改签名 [`39954e7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/39954e7e5ea39f4f587ecdf232553a245f930e1a)
+
+## [v0.4.1](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.4.0...v0.4.1) - 2018-03-30
+
+### Commits
+
+- 修改 md5 算法 [`df7b964`](https://github.com/tencentyun/cos-js-sdk-v5/commit/df7b96402895191613f9c8c8746ff7ced96f173b)
+- 修改 md5 算法 [`47b39db`](https://github.com/tencentyun/cos-js-sdk-v5/commit/47b39db6e1f3e27591cc81f469dcf989719e0aed)
+
+## [v0.4.0](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.3.11...v0.4.0) - 2018-03-26
+
+* 签名支持 Query 和 Headers 参数
+* 完善后端例子,默认签名权限收拢到只能上传文件
+
+### Commits
+
+- 修改签名方式,保证安全性 [`0fa7b69`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0fa7b69cfc179129f75d034d5536c3b6905c0130)
+- Update sts-form.html [`c592a41`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c592a4103ed105b6e79b3dbdc2bb40a7ec1e17d5)
+- Update sts-put.html [`f881cbc`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f881cbcb938f26412759744130d532362921f318)
+- Update sts-post.html [`445b307`](https://github.com/tencentyun/cos-js-sdk-v5/commit/445b3079efe8f38eb69b5ce6cb0ffe88b6422b64)
+- Update simple-form.html [`bcb7516`](https://github.com/tencentyun/cos-js-sdk-v5/commit/bcb751630687b7c2ffe43f654c6176c4667c4909)
+- Update simple-put.html [`4b251bb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4b251bb5e0b7bb0a1c1ee2419f442dfc4b6a9c16)
+- Update simple-post.html [`e09852a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e09852aeb366d2f56a4397abf6e8c9158cfe36c8)
+- Update simple-put.html [`7dd80af`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7dd80af39ba70fec06b01869e9e2ef85cfa4da85)
+- Update simple-post.html [`7678c80`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7678c80a530d807408c89cd0fc9d76bd4df88fab)
+
+## [v0.3.11](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.3.10...v0.3.11) - 2018-03-15
+
+* 添加 Protocol 参数支持
+* 如果页面不是 http: 协议,默认使用 https: 协议
+* 优化返回数据的容错处理
+* 优化 Region 错误格式判断
+* 优化参数对象污染问题
+
+### Commits
+
+- 修改容错 [`2dac011`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2dac0118c22d8c3298a51129f1d20dd8f664ae46)
+- 优化错误提示 [`287118b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/287118b79e3d52bacc26fe470f0ffca421918d5a)
+- 支持自定义 Protocol [`1bedb79`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1bedb79f5503ba97afaff46db6bfae5ce75af3c0)
+- 优化参数污染问题 [`ee1626e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ee1626e72cc8b35976a38156fcf19e3de9315819)
+- 删除调试域名 [`aa58fbc`](https://github.com/tencentyun/cos-js-sdk-v5/commit/aa58fbc2a00260c3b15a237c469997255eb153e0)
+- Update sts-put.html [`7964253`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7964253101e4a681229197ee530934e1562ef381)
+- update test [`3e8bced`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3e8bcedc11d2222a975ae9c66fe7fb68121409be)
+
+## [v0.3.10](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.3.9...v0.3.10) - 2018-03-06
+
+### Commits
+
+- 修复 putObject 传空字符串的报错 [`4dc8ef5`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4dc8ef5c484706e4371c22f90cadae49683af0bf)
+
+## [v0.3.9](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.3.7...v0.3.9) - 2018-03-06
+
+* 支持多版本,多个接口支持 VersionId 参数
+* 支持自定义 Header 参数
+* 支持 SSE 服务端加密参数
+
+### Commits
+
+- 支持多版本 [`c515c44`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c515c4446a0f97088134549a4da51f0c8b507435)
+- support SSE [`fb99f7c`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fb99f7c52d89e00322d5a29c2596212a6b10b9e2)
+- support SSE [`ff339a8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ff339a878eb0f34aaf4d2a4a6e8cfb4f3d87f218)
+- getSTS demo [`08fbe71`](https://github.com/tencentyun/cos-js-sdk-v5/commit/08fbe71924f90aadf33ca561ad6fdee501ca0c31)
+- Update README.md [`dc3b48b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/dc3b48b3cfc3519d643312adb7966e4ba4ef491a)
+- 自动计算分片大小 [`8f00724`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8f00724765045989263314898f14220d426e562a)
+- 支持多版本 [`4c8f9ce`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4c8f9ce64b4764f03cd2f9b24139e1bdab21abda)
+- Update README.md [`6ce6798`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6ce6798c94a6b548536f2e547537ffc0b7793cbe)
+- 自动计算分片大小 [`2dba7d6`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2dba7d6662e0bcfed55c38d5a981f887d8616666)
+- support SSE [`5037759`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5037759c527d746526ab7c746fa1468d7cfef1e6)
+- support SSE [`b4d8df1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b4d8df1c1eb35b2dc360f6a04a26bb4fde72288f)
+- 删掉多余代码 [`f10f418`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f10f418396fbbd5cacb77767ce04199a70e42945)
+
+## [v0.3.7](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.3.6...v0.3.7) - 2018-01-16
+
+### Commits
+
+- 自动计算分片大小 [`6a8042e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6a8042e051ca037330bec45905ebd20f55c682b9)
+- update demo [`4257d09`](https://github.com/tencentyun/cos-js-sdk-v5/commit/4257d093ab981d16e5876271cbf1b704643ac35e)
+- 容错 [`d9e58a9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d9e58a96f98399d983dcf9373e791255ea503884)
+- update demo [`110aecf`](https://github.com/tencentyun/cos-js-sdk-v5/commit/110aecf2bcd276c5c43e80a4b64a981ee842c732)
+- Update README.md [`dee6626`](https://github.com/tencentyun/cos-js-sdk-v5/commit/dee66266cf8ed49ce0e8f9aeea80fc0c0ef2c10f)
+- update demo [`905bc7b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/905bc7bfb61ef57f8fe5f2c8131d4273ee096b50)
+
+## [v0.3.6](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.2.0...v0.3.6) - 2018-01-12
+
+* 去掉 AppId 概念,Bucket 需要传入这样的格式 test -1250000000
+* 修复多个问题
+* 新增多个接口
+
+### Commits
+
+- v0.3.3 新增 getObjectUrl 接口 [`801e677`](https://github.com/tencentyun/cos-js-sdk-v5/commit/801e6779e145451d2d16856df2baf498a12e8257)
+- 修复 test-123-1250000000 bucket 分片上传出错问题 [`b915a89`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b915a892f10fb16054ac387a17b2fdba25b85610)
+- 优化接口返回值 [`8f009f9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8f009f9103b279354d5daca718d52ca5f9557a5a)
+- 修改 Location 错误 [`13c3044`](https://github.com/tencentyun/cos-js-sdk-v5/commit/13c3044f9c37330afa6e120ef4c4b587f75653bd)
+- 修复 ContentLength 错误 [`5010b4b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5010b4b882eab4438a918fbd6c4801bcb3884b51)
+- 容错 [`e6563c0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e6563c08eff78112d376dc8678122cf498ebb3d0)
+- Update README.md [`fd018a8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fd018a8fd2680ee97e10673bbfe2ed6d03e4887e)
+- 修改 demo [`b5ebbab`](https://github.com/tencentyun/cos-js-sdk-v5/commit/b5ebbaba9a8e469fc0601c13fcc01fab59ea19fc)
+- 修改 demo [`043bada`](https://github.com/tencentyun/cos-js-sdk-v5/commit/043badad6ed6840e324dc1aaf9484c25a308d3a4)
+- Update auth.php [`bb6c0e4`](https://github.com/tencentyun/cos-js-sdk-v5/commit/bb6c0e4870c29651f41e02271f632fe3d618d6fa)
+- 修改文档 [`c50942b`](https://github.com/tencentyun/cos-js-sdk-v5/commit/c50942bbe773d8b5d41becf6b62f1781674e1cb9)
+- Update README.md [`ef9f8ea`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ef9f8ea0798367129b86c96d66f682a586491ee9)
+- Update demo.js [`39666a9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/39666a9a1a735358c65d9fedcac3c5a7211c7396)
+- 修改 auth 例子 [`0e55af7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0e55af787f58af7578ed21729174cad35da320d3)
+
+## [v0.2.0](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.0.8...v0.2.0) - 2017-11-01
+
+* 压缩版代码精简到 108 KB
+* 删除 xml2js、async、EventProxy node 模块,用简单的代码实现需要的接口
+* 更改 task 相关事件和触发逻辑,只提供 list-update 事件
+* 修复 onProgress 返回速度为负数的问题
+* 完善测试用例
+* 上传过程获取不到响应 header 里的 ETag,会提示配置 CORS ExposeHeader 允许 ETag 字段
+
+### Commits
+
+- 更新 dist [`1922440`](https://github.com/tencentyun/cos-js-sdk-v5/commit/19224408b8813c1533c6aa5e716f639a2bf4e47d)
+- fix error [`afc0914`](https://github.com/tencentyun/cos-js-sdk-v5/commit/afc091428c932c119b66012d85f9b5d06ee851eb)
+- fix error [`6d32142`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6d32142b201361e8facfc13d3ef6185ae03eeff3)
+- 整理 acl 返回值 [`490a28d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/490a28dfe26e0b5dc9cb7196afd2bad7bba13d15)
+- version 0.1.4 [`8d64069`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8d640699d40f65faca3a901da2d7a26a3e216fba)
+- 更新 get acl [`f85d5e0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f85d5e0b406c3822db2c9be27b7e82e40cf1de8e)
+- 删除无用文件 [`e451781`](https://github.com/tencentyun/cos-js-sdk-v5/commit/e4517815e31b0301a781b51c05f54f53672a83e1)
+- 修改 onProgress [`605a895`](https://github.com/tencentyun/cos-js-sdk-v5/commit/605a8956f238c70e8c42f27c3ac3fb214db5af7f)
+- 修改用例和 demo [`6109e54`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6109e54b223e482ed3f02a552363b15f6db3ccd2)
+- 更换 xml 和 json 转换的库 [`48a755e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/48a755efacfa7c09a9d22fe997a77f12993f5b2d)
+- 修改签名计算 [`cfff58f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cfff58fc2cc2cda803efde418a7655f7b84b8f38)
+- 修改 region [`9979420`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9979420c283e0c9756edff21d0e06665d9bfa165)
+- 修复报错,修改签名参数 [`ccf9017`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ccf901731b3b8d8bd0e6a23871f7098c36115009)
+- CORS AllowHeader 例子改成 * [`0a4d5af`](https://github.com/tencentyun/cos-js-sdk-v5/commit/0a4d5afe97bf3aa297651cac9896eb974be9e76a)
+- 修改 Readme [`75cb126`](https://github.com/tencentyun/cos-js-sdk-v5/commit/75cb126d3a3d148df16df86bec1b49b35ffe473f)
+- 修改队列处理 [`d8f856e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d8f856eb698bde8b3c1e20be62b16c62392800fc)
+- 如掉 async 模块引用 [`7f16e51`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7f16e5112d05160b86026efc3d19c5692ed44e76)
+- 修改版本号和 webpack 配置 [`000dd1e`](https://github.com/tencentyun/cos-js-sdk-v5/commit/000dd1eba7d79f424608eb0d3a90a6708c1b1a88)
+- Create LICENSE [`db76da5`](https://github.com/tencentyun/cos-js-sdk-v5/commit/db76da5a5e721c693c712982d088f86e953c9f6d)
+- 旧的region域名不带cos. [`ca48fea`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ca48feac74f227f1be5fe322797d1555142ea1fe)
+
+## [v0.0.8](https://github.com/tencentyun/cos-js-sdk-v5/compare/v0.0.6...v0.0.8) - 2017-09-01
+
+* 支持多个 Bucket 接口
+* 分片上传支持续传
+
+### Merged
+
+- 修复默认参数异常问题 [`#1`](https://github.com/tencentyun/cos-js-sdk-v5/pull/1)
+
+### Commits
+
+- 添加自测用例 [`a0b6fbd`](https://github.com/tencentyun/cos-js-sdk-v5/commit/a0b6fbdb40f75012ffd36a5c46dcfe0c9e8c8d59)
+- 添加 Location [`2251605`](https://github.com/tencentyun/cos-js-sdk-v5/commit/22516058f14edbd5cd1b8a403e048746e4f17b12)
+- 添加 policy 规则 [`aba0403`](https://github.com/tencentyun/cos-js-sdk-v5/commit/aba04033e9750e9c09eacfe55ef5f9b133f3cc40)
+- 去除两个一定跨域的方法 [`18c7825`](https://github.com/tencentyun/cos-js-sdk-v5/commit/18c782507e98a2bad0013a1e0b40f8789babcff3)
+- 支持 bucket 操作,支持分片续传 [`86b8ee7`](https://github.com/tencentyun/cos-js-sdk-v5/commit/86b8ee704ed82e1646fcf21034791a8593ac2396)
+- 优化demo [`2a5e27d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2a5e27df776bb28a9108944be38f54680db9dd93)
+- 优化 [`fbe9f17`](https://github.com/tencentyun/cos-js-sdk-v5/commit/fbe9f179c8619876d396ec4cb810230677d86e3e)
+- 优化代码 [`3853e15`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3853e150fde27492c2b4ce11eb7e9c1c1446b86b)
+- 修复json请求错误 [`01fc8bb`](https://github.com/tencentyun/cos-js-sdk-v5/commit/01fc8bbca01ba8a904047bcc68f2958135e37852)
+- 修复进度抖动问题 [`2f16a13`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2f16a134b86dcd828ff318003b659b141616026a)
+- 修改签名 [`3fbe13a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3fbe13af5c48930fd33a9fda939cbe349c4354e2)
+- 修改签名 [`de48541`](https://github.com/tencentyun/cos-js-sdk-v5/commit/de48541039c1ec211e3a2f7566ba43e32478c12a)
+- lifecycle [`8543650`](https://github.com/tencentyun/cos-js-sdk-v5/commit/85436501cb6cf38b62ced4b10f93ffbe930d8637)
+- change version [`30ce5c9`](https://github.com/tencentyun/cos-js-sdk-v5/commit/30ce5c931b9043bbc5f3ca9b6ff0cd2957865a2a)
+- change version [`eb9257d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/eb9257dddf6a719391d7bb5c835c9e3da769f912)
+- 修改 CORS 配置 [`1eee838`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1eee8383bf4595868920d24bee67883a0dbf5ea5)
+- 修改 ak [`5d80cf2`](https://github.com/tencentyun/cos-js-sdk-v5/commit/5d80cf2e9330330e24a5972e9145082fecc94da0)
+- 修复PutBucketPolicy错误 [`734a212`](https://github.com/tencentyun/cos-js-sdk-v5/commit/734a2129d608ee977699b636c5140934b22c4fb0)
+- 修改 demo 中的 cors.png 图片 [`6758c8a`](https://github.com/tencentyun/cos-js-sdk-v5/commit/6758c8a4e8a01edb75ee9b54a10f41ae5059037e)
+
+## v0.0.6 - 2017-07-20
+
+* 支持简单上传
+* 支持分片上传
+* 支持分片并发、分片错误重试、文件并发控制
+* 支持对上传任务取消、暂停、开始操作
+* 支持一些基本的 Bucket、Object 操作接口
+
+### Commits
+
+- fix upload [`915ea79`](https://github.com/tencentyun/cos-js-sdk-v5/commit/915ea7951ce2139f1450a5456bc1783ec62767c2)
+- init [`054e1c1`](https://github.com/tencentyun/cos-js-sdk-v5/commit/054e1c132e55feba5a41546b9032af70686071e5)
+- fix getService https [`2fd887f`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2fd887f95bc5b00ae8d0f69ba2fbec773cbad367)
+- update [`9bb221d`](https://github.com/tencentyun/cos-js-sdk-v5/commit/9bb221dcff20a3ca44cd53e8f6015fa653a96b20)
+- add event and task [`3658086`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3658086534c53b49f09428d2d6f6ad650bb57fc6)
+- modify api [`d88d8fa`](https://github.com/tencentyun/cos-js-sdk-v5/commit/d88d8fa6a9b3683ca09bdd3e86f8aa1f67846192)
+- add status and headers [`7ecf480`](https://github.com/tencentyun/cos-js-sdk-v5/commit/7ecf4806e5276eb17de92564dc21d7421ce29859)
+- 支持自定义域名 [`cacaa43`](https://github.com/tencentyun/cos-js-sdk-v5/commit/cacaa43a2c62259ae0341f45faeb49c77913290e)
+- fix task bug [`8ebb524`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8ebb5244c17cef31ef8da82397c7b13dd1d70953)
+- modify get acl [`8020b23`](https://github.com/tencentyun/cos-js-sdk-v5/commit/8020b23c8f7109afaf52b832cf5b9ed61da0d920)
+- add task demo [`20a67b0`](https://github.com/tencentyun/cos-js-sdk-v5/commit/20a67b0bd2a4655ab915f5ba86ff0558764f28e3)
+- remove data=data||{}; [`1c149d3`](https://github.com/tencentyun/cos-js-sdk-v5/commit/1c149d38b5a1e0ad2bfb7cda089e24204c6dc39c)
+- modify readme [`f1d6c16`](https://github.com/tencentyun/cos-js-sdk-v5/commit/f1d6c16f19e7b3f096fbb407dca05a714dfdff33)
+- fix !'()* url encode error [`04e4df8`](https://github.com/tencentyun/cos-js-sdk-v5/commit/04e4df8f0a74d474c972980405b132a57b4abca7)
+- fix https error [`3dada36`](https://github.com/tencentyun/cos-js-sdk-v5/commit/3dada36eab9ce1fda060d00a8cef4d65ef9caf08)
+- fix onProgress error [`2248622`](https://github.com/tencentyun/cos-js-sdk-v5/commit/22486225ceece9ed0b8c639d34b30ecd6beff166)
+- can cancel paused [`46e9e87`](https://github.com/tencentyun/cos-js-sdk-v5/commit/46e9e877092ac0d11afe8bca292f134d92b34031)
+- fix ContentLength error [`2ef7742`](https://github.com/tencentyun/cos-js-sdk-v5/commit/2ef77425a3a445f317cf26748512ce873c706715)
+- modify options [`2819843`](https://github.com/tencentyun/cos-js-sdk-v5/commit/28198438e3d216706c135b9e5181961c8faa8d84)
+- remove useless [`ccf11de`](https://github.com/tencentyun/cos-js-sdk-v5/commit/ccf11de4b6135d71c21800f4ac976a093b00a64f)

+ 21 - 0
node_modules/cos-js-sdk-v5/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present 腾讯云
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 111 - 0
node_modules/cos-js-sdk-v5/README.md

@@ -0,0 +1,111 @@
+# cos-js-sdk-v5
+
+腾讯云 COS JS SDK([XML API](https://cloud.tencent.com/document/product/436/7751))
+
+[releases and changelog](https://github.com/tencentyun/cos-js-sdk-v5/releases)
+
+## Get started
+
+### 一、前期准备
+
+1. 首先,JS SDK 需要浏览器支持基本的 HTML5 特性,以便支持 ajax 上传文件和计算文件 md5 值。
+2. 到 [COS对象存储控制台](https://console.cloud.tencent.com/cos) 创建存储桶,得到 Bucket(存储桶名称) 和 [Region(地域名称)](https://cloud.tencent.com/document/product/436/6224)
+3. 到 [控制台密钥管理](https://console.cloud.tencent.com/capi) 获取您的项目 SecretId 和 SecretKey
+4. 配置 CORS 规则,配置例子如下图:
+
+![cors](demo/cors.png)
+
+### 二、计算签名
+
+由于签名计算放在前端会暴露 SecretId 和 SecretKey,我们把签名计算过程放在后端实现,前端通过 ajax 向后端获取签名结果,正式部署时请再后端加一层自己网站本身的权限检验。
+
+这里提供 [PHP 和 NodeJS 的签名例子](https://github.com/tencentyun/cos-js-sdk-v5/blob/master/server/),其他语言,请参照对应的 [XML SDK](https://cloud.tencent.com/document/product/436/6474)
+
+### 三、上传例子
+
+1. 创建 test.html,填入下面的代码,修改里面的 Bucket 和 Region。
+2. 部署好后端的签名服务,并修改 getAuthorization 里的签名服务地址
+3. 把 test.html 放在 Web 服务器下,然后在浏览器访问页面,测试文件上传
+
+```html
+<input id="file-selector" type="file">
+<script src="dist/cos-js-sdk-v5.min.js"></script>
+<script>
+var Bucket = 'test-1250000000';
+var Region = 'ap-guangzhou';
+
+// 初始化实例
+var cos = new COS({
+    getAuthorization: function (options, callback) {
+        var url = '../server/sts.php'; // 这里替换成您的服务接口地址
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', url, true);
+        xhr.onload = function (e) {
+            try {
+                var data = JSON.parse(e.target.responseText);
+                var credentials = data.credentials;
+            } catch (e) {
+            }
+            if (!data || !credentials) return console.error('credentials invalid');
+            callback({
+                TmpSecretId: credentials.tmpSecretId,
+                TmpSecretKey: credentials.tmpSecretKey,
+                XCosSecurityToken: credentials.sessionToken,
+                StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
+                ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000900
+            });
+        };
+        xhr.send();
+    }
+});
+
+// 监听选文件
+document.getElementById('file-selector').onchange = function () {
+
+    var file = this.files[0];
+    if (!file) return;
+
+    // 分片上传文件
+    cos.sliceUploadFile({
+        Bucket: Bucket,
+        Region: Region,
+        Key: file.name,
+        Body: file,
+        onHashProgress: function (progressData) {
+            console.log('校验中', JSON.stringify(progressData));
+        },
+        onProgress: function (progressData) {
+            console.log('上传中', JSON.stringify(progressData));
+        },
+    }, function (err, data) {
+        console.log(err, data);
+    });
+
+};
+</script>
+```
+
+
+## webpack 引入方式
+
+支持 webpack 打包的场景,可以用 npm 引入作为模块
+```shell
+npm i cos-js-sdk-v5 --save
+```
+
+## Start Demo
+```
+1. git clone cos-js-sdk-v5 至本地
+2. cd cos-js-sdk-v5
+3. 修改 server 文件夹中 sts.js 或 sts.php 中的 secretId、secretKey、bucket、region 配置
+4. npm run server # 用 node 启动服务
+5. 浏览器输入 http://127.0.0.1:3000/ 即可进行 demo 演示
+```
+
+## 说明文档
+
+[使用例子](demo/demo.js)
+
+[快速入门](https://cloud.tencent.com/document/product/436/11459)
+
+[接口文档](https://cloud.tencent.com/document/product/436/12260)

+ 17 - 0
node_modules/cos-js-sdk-v5/bower.json

@@ -0,0 +1,17 @@
+{
+  "name": "cos-js-sdk-v5",
+  "description": "cos js sdk v5",
+  "main": "dist/cos-js-sdk-v5.min.js",
+  "authors": [
+    "carsonxu"
+  ],
+  "license": "ISC",
+  "homepage": "https://github.com/tencentyun/cos-js-sdk-v5",
+  "ignore": [
+    "**/.*",
+    "node_modules",
+    "bower_components",
+    "test",
+    "tests"
+  ]
+}

+ 79 - 0
node_modules/cos-js-sdk-v5/csp/AllowAction.md

@@ -0,0 +1,79 @@
+# 允许操作的判断例子
+
+以下按照 JavaScript 为例子,列举签名允许操作的判断规则
+
+```js
+var exist = function (obj, key) {
+    return obj[key] === undefined;
+};
+```
+
+## 分片上传
+
+```js
+// multipartList 获取已有上传任务
+if (pathname === '/' && method === 'get' && exist(query['uploads'])) allow = true;
+// multipartListPart 获取单个上传任务的分片列表
+if (pathname !== '/' && method === 'get' && exist(query['uploadId'])) allow = true;
+// multipartInit 初始化分片上传
+if (pathname !== '/' && method === 'post' && exist(query['uploads'])) allow = true;
+// multipartUpload 上传文件的单个分片
+if (pathname !== '/' && method === 'put' && exist(query['uploadId']) && exist(query['partNumber'])) allow = true;
+// multipartComplete 完成一次分片上传
+if (pathname !== '/' && method === 'post' && exist(query['uploadId'])) allow = true;
+```
+
+## 简单上传
+
+```js
+// putObject 简单上传文件
+if (pathname !== '/' && method === 'put' && !exist(query['acl'])) allow = true;
+// postObject 允许表单上传文件
+if (pathname === '/' && method === 'post' && !exist(query['delete'])) allow = true;
+```
+
+## 获取和修改权限策略
+
+```js
+// getBucketAcl 获取 Bucket 权限
+if (pathname === '/' && method === 'get' && !exist(query['acl'])) allow = true;
+// putBucketAcl 修改 Bucket 权限
+if (pathname === '/' && method === 'put' && !exist(query['acl'])) allow = true;
+// getBucketPolicy 获取权限策略
+if (pathname === '/' && method === 'get' && !exist(query['policy'])) allow = true;
+// putBucketPolicy 修改权限策略
+if (pathname === '/' && method === 'put' && !exist(query['policy'])) allow = true;
+// getObjectAcl 获取 Object 权限
+if (pathname !== '/' && method === 'get' && !exist(query['acl'])) allow = true;
+// putObjectAcl 修改 Object 权限
+if (pathname !== '/' && method === 'put' && !exist(query['acl'])) allow = true;
+```
+
+## 获取和修改生命周期
+
+```js
+// getBucketLifecycle 获取 Bucket Lifecycle
+if (pathname === '/' && method === 'get' && !exist(query['lifecycle'])) allow = true;
+// putBucketLifecycle 修改 Bucket Lifecycle
+if (pathname === '/' && method === 'put' && !exist(query['lifecycle'])) allow = true;
+```
+
+## 获取和修改 Tagging
+
+```js
+// getBucketTagging 获取 Bucket Tagging
+if (pathname === '/' && method === 'get' && !exist(query['tagging'])) allow = true;
+// putBucketTagging 修改 Bucket Tagging
+if (pathname === '/' && method === 'put' && !exist(query['tagging'])) allow = true;
+// deleteBucketTagging 删除 Bucket Tagging
+if (pathname === '/' && method === 'delete' && !exist(query['tagging'])) allow = true;
+```
+
+## 删除文件
+
+```js
+// deleteMultipleObject 批量删除文件
+if (pathname === '/' && method === 'post' && !exist(query['delete'])) allow = true;
+// deleteObject 删除单个文件
+if (pathname !== '/' && method === 'delete') allow = true;
+```

+ 7 - 0
node_modules/cos-js-sdk-v5/csp/README.md

@@ -0,0 +1,7 @@
+# COS JavaScript SDK CSP 使用文档
+
+[快速入门](./start.md)
+
+[API 文档](./api.md)
+
+[示例代码](./csp.html)

Разница между файлами не показана из-за своего большого размера
+ 1936 - 0
node_modules/cos-js-sdk-v5/csp/api.md


+ 156 - 0
node_modules/cos-js-sdk-v5/csp/auth-json.php

@@ -0,0 +1,156 @@
+<?php
+
+/**
+ * php 签名样例
+ */
+
+function isActionAllow($method, $pathname, $query, $headers)
+{
+
+    $allow = true;
+
+    // // TODO 这里判断自己网站的登录态
+    // if ($!logined) {
+    //     $allow = false;
+    //     return $allow;
+    // }
+
+    // 请求可能带有点所有 action
+    // acl,cors,policy,location,tagging,lifecycle,versioning,replication,versions,delete,restore,uploads
+
+    // 请求跟路径,只允许获取 UploadId
+    if ($pathname === '/' && !($method === 'get' && isset($query['uploads']))) {
+        $allow = false;
+    }
+
+    // 不允许前端获取和修改文件权限
+    if ($pathname !== '/' && isset($query['acl'])) {
+        $allow = false;
+    }
+
+    // 这里应该根据需要,限制当前站点的用户只允许操作什么样的路径
+    if ($method === 'delete' && $pathname !== '/') { // 这里控制是否允许删除文件
+        // TODO 这里控制是否允许删除文件
+    }
+    if ($method === 'put' && $pathname !== '/') { // 这里控制是否允许上传和修改文件
+        // TODO 这里控制是否允许上传和修改文件
+    }
+    if ($method === 'get' && $pathname !== '/') { // 这里控制是否获取文件和文件相关信息
+        // TODO 这里控制是否允许获取文件和文件相关信息
+    }
+
+    return $allow;
+
+}
+
+/*
+ * 获取签名
+ * @param string $method 请求类型 method
+ * @param string $pathname 文件名称
+ * @param array $query query参数
+ * @param array $headers headers
+ * @return string 签名字符串
+ */
+function getAuthorization($method, $pathname, $query, $headers)
+{
+
+    // 获取个人 API 密钥 https://console.qcloud.com/capi
+    $SecretId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+    $SecretKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
+
+    // 整理参数
+    !$query && ($query = array());
+    !$headers && ($headers = array());
+    $method = strtolower($method ? $method : 'get');
+    $pathname = $pathname ? $pathname : '/';
+    substr($pathname, 0, 1) != '/' && ($pathname = '/' . $pathname);
+
+    // 注意这里要过滤好允许什么样的操作
+    if (!isActionAllow($method, $pathname, $query, $headers)) {
+        return 'action deny';
+    }
+
+    // 工具方法
+    function getObjectKeys($obj)
+    {
+        $list = array_keys($obj);
+        sort($list);
+        return $list;
+    }
+
+    function obj2str($obj)
+    {
+        $list = array();
+        $keyList = getObjectKeys($obj);
+        $len = count($keyList);
+        for ($i = 0; $i < $len; $i++) {
+            $key = $keyList[$i];
+            $val = isset($obj[$key]) ? $obj[$key] : '';
+            $key = strtolower($key);
+            $list[] = rawurlencode($key) . '=' . rawurlencode($val);
+        }
+        return implode('&', $list);
+    }
+
+    // 签名有效起止时间
+    $now = time() - 1;
+    $expired = $now + 600; // 签名过期时刻,600 秒后
+
+    // 要用到的 Authorization 参数列表
+    $qSignAlgorithm = 'sha1';
+    $qAk = $SecretId;
+    $qSignTime = $now . ';' . $expired;
+    $qKeyTime = $now . ';' . $expired;
+    $qHeaderList = strtolower(implode(';', getObjectKeys($headers)));
+    $qUrlParamList = strtolower(implode(';', getObjectKeys($query)));
+
+    // 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
+    // 步骤一:计算 SignKey
+    $signKey = hash_hmac("sha1", $qKeyTime, $SecretKey);
+
+    // 步骤二:构成 FormatString
+    $formatString = implode("\n", array(strtolower($method), $pathname, obj2str($query), obj2str($headers), ''));
+
+    // 步骤三:计算 StringToSign
+    $stringToSign = implode("\n", array('sha1', $qSignTime, sha1($formatString), ''));
+
+    // 步骤四:计算 Signature
+    $qSignature = hash_hmac('sha1', $stringToSign, $signKey);
+
+    // 步骤五:构造 Authorization
+    $authorization = implode('&', array(
+        'q-sign-algorithm=' . $qSignAlgorithm,
+        'q-ak=' . $qAk,
+        'q-sign-time=' . $qSignTime,
+        'q-key-time=' . $qKeyTime,
+        'q-header-list=' . $qHeaderList,
+        'q-url-param-list=' . $qUrlParamList,
+        'q-signature=' . $qSignature
+    ));
+
+    return $authorization;
+}
+
+
+// 获取前端过来的参数
+$inputBody = file_get_contents("php://input");
+if ($_SERVER['REQUEST_METHOD'] === 'POST' && $inputBody){
+    $params = json_decode($inputBody, 1);
+    $pathname = isset($params['pathname']) ? $params['pathname'] : '/';
+    $method = isset($params['method']) ? $params['method'] : 'get';
+    $query = isset($params['query']) ? $params['query'] : array();
+    $headers = isset($params['headers']) ? $params['headers'] : array();
+} else {
+    $pathname = isset($_GET['pathname']) ? $_GET['pathname'] : '/';
+    $method = isset($_GET['method']) ? $_GET['method'] : 'get';
+    $query = isset($_GET['query']) && $_GET['query'] ? json_decode($_GET['query'], 1) : array();
+    $headers = isset($_GET['headers']) && $_GET['headers'] ? json_decode($_GET['headers'], 1) : array();
+}
+
+// 返回数据给前端
+header('Content-Type: text/plain');
+header('Allow-Control-Allow-Origin: http://127.0.0.1'); // 这里修改允许跨域访问的网站
+header('Allow-Control-Allow-Headers: origin,accept,content-type');
+$sign = getAuthorization($method, $pathname, $query, $headers);
+
+echo '{"sign":"' . $sign .'"}';

+ 651 - 0
node_modules/cos-js-sdk-v5/csp/csp.html

@@ -0,0 +1,651 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>cos-js-sdk-v5</title>
+    <style>
+        body { font-family: "Microsoft YaHei"; }
+        .page {max-width:1024px;margin:0 auto;}
+        h1 { font-weight: normal; color:#333;}
+        a { color: #006eff; background-color: transparent; padding: 8px 16px; line-height: 1.3; display: inline-block; text-align: center; margin: 0 8px 8px 0; border: 1px solid #006eff; font-size: 14px; text-decoration: none; }
+        a:hover { color: #fff; background-color: #006eff; }
+        .result {display:none;line-height:1.3;font-size: 13px;font-family:monospace;border:1px solid #006eff;margin:0;height:200px;overflow:auto;box-sizing:border-box;padding:5px;}
+    </style>
+</head>
+<body>
+
+<div class="page">
+    <h1>cos-js-sdk-v5</h1>
+    <div class="main"></div>
+    <pre class="result"></pre>
+</div>
+
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script>
+    var config = {
+        Bucket: 'test-1250000000',
+        Region: 'default'
+    };
+
+    var util = {
+        createFile: function (options) {
+            var buffer = new ArrayBuffer(options.size || 0);
+            var arr = new Uint8Array(buffer);
+            [].forEach.call(arr, function (char, i) {
+                arr[i] = 0;
+            });
+            var opt = {};
+            options.type && (opt.type = options.type);
+            var blob = new Blob([buffer], options);
+            return blob;
+        }
+    };
+
+    var cos = new COS({
+        CompatibilityMode: true,
+        ServiceDomain: 'http://cos.default.example.com',
+
+        // 后缀式
+        Domain: 'http://cos.{Region}.example.com', // 后缀式
+        ForcePathStyle: true, // 后缀式
+
+        // 前缀式
+        // Domain: 'http://{Bucket}.cos.{Region}.example.com', // 前缀式
+
+        getAuthorization: function (options, callback) {
+            var url = './auth-json.php?method=' + options.Method + '&path=' + encodeURIComponent(options.Key);
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onload = function (e) {
+                var sign;
+                try {
+                    sign = JSON.parse(e.target.responseText).sign;
+                } catch (e) {}
+                callback(sign);
+            };
+            xhr.send();
+        },
+    });
+
+    var TaskId;
+
+    var pre = document.querySelector('.result');
+    var showLogText = function (text, color) {
+        if (typeof text === 'object') {
+            try {
+                text = JSON.stringify(text);
+            } catch (e) {
+            }
+        }
+        var div = document.createElement('div');
+        div.innerText = text;
+        color && (div.style.color = color);
+        pre.appendChild(div);
+        pre.style.display = 'block';
+        pre.scrollTop = pre.scrollHeight;
+    };
+
+    var logger = {
+        log: function (text) {
+            console.log.apply(console, arguments);
+            showLogText([].join.call(arguments, ' '));
+        },
+        error: function (text) {
+            console.error(text);
+            showLogText(text, 'red');
+        },
+    };
+
+    function getObjectUrl() {
+        var url = cos.getObjectUrl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip',
+            Expires: 60,
+            Sign: true,
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+        logger.log(url);
+    }
+
+    function getBucket() {
+        cos.getBucket({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function headBucket() {
+        cos.headBucket({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putBucketAcl() {
+        cos.putBucketAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            // GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantWrite: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantRead: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantReadAcp: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantWriteAcp: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // ACL: 'public-read-write',
+            // ACL: 'public-read',
+            ACL: 'private',
+            // AccessControlPolicy: {
+            // "Owner": { // AccessControlPolicy 里必须有 owner
+            //     "ID": 'qcs::cam::uin/459000000:uin/459000000' // 459000000 是 Bucket 所属用户的 uin(帐号ID)
+            // },
+            // "Grants": [{
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/1001:uin/1001", // 10002 是 uin(帐号ID)
+            //         "DisplayName": "qcs::cam::uin/1001:uin/1001" // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "READ"
+            // }, {
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "WRITE"
+            // }, {
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "READ_ACP"
+            // }, {
+            //     "Grantee": {
+            //         "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //     },
+            //     "Permission": "WRITE_ACP"
+            // }]
+            // }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketAcl() {
+        cos.getBucketAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putBucketCors() {
+        cos.putBucketCors({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            CORSConfiguration: {
+                "CORSRules": [{
+                    "AllowedOrigin": ["*"],
+                    "AllowedMethod": ["GET", "POST", "PUT", "DELETE", "HEAD"],
+                    "AllowedHeader": ["*"],
+                    "ExposeHeader": ["ETag", "x-cos-acl", "x-cos-delete-marker", "x-cos-server-side-encryption"],
+                    "MaxAgeSeconds": "5"
+                }]
+            }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketCors() {
+        cos.getBucketCors({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteBucketCors() {
+        cos.deleteBucketCors({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketLocation() {
+        cos.getBucketLocation({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putBucketLifecycle() {
+        cos.putBucketLifecycle({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            LifecycleConfiguration: {
+                "Rules": [{
+                    'ID': 1,
+                    'Filter': {
+                        'Prefix': 'test123',
+                    },
+                    'Status': 'Enabled',
+                    'Transition': {
+                        'Date': '2016-10-31T00:00:00+08:00',
+                        'StorageClass': 'STANDARD_IA'
+                    }
+                }]
+            }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getBucketLifecycle() {
+        cos.getBucketLifecycle({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteBucketLifecycle() {
+        cos.deleteBucketLifecycle({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteBucket() {
+        cos.deleteBucket({
+            Bucket: 'testnew-' + config.Bucket.substr(config.Bucket.lastIndexOf('-') + 1),
+            Region: 'ap-guangzhou'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putObject() {
+        // 创建测试文件
+        var filename = '1kb.zip';
+        var blob = util.createFile({size: 1024});
+        // 调用方法
+        cos.putObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: filename, /* 必须 */
+            Body: blob,
+            TaskReady: function (tid) {
+                TaskId = tid;
+            },
+            onProgress: function (progressData) {
+                logger.log(JSON.stringify(progressData));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putObjectCopy() {
+        cos.putObjectCopy({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.copy.zip',
+            CopySource: config.Bucket + '.cos.' + config.Region + '.myqcloud.com/' + encodeURIComponent('1mb.zip').replace(/%2F/g, '/'), // Bucket 格式:test-1250000000
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getObject() {
+        cos.getObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip',
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function headObject() {
+        cos.headObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function putObjectAcl() {
+        cos.putObjectAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip',
+            // GrantFullControl: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantWrite: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // GrantRead: 'id="qcs::cam::uin/1001:uin/1001",id="qcs::cam::uin/1002:uin/1002"',
+            // ACL: 'public-read-write',
+            // ACL: 'public-read',
+            // ACL: 'private',
+            ACL: 'default', // 继承上一级目录权限
+            // AccessControlPolicy: {
+            //     "Owner": { // AccessControlPolicy 里必须有 owner
+            //         "ID": 'qcs::cam::uin/459000000:uin/459000000' // 459000000 是 Bucket 所属用户的 uin(帐号ID)
+            //     },
+            //     "Grants": [{
+            //         "Grantee": {
+            //             "ID": "qcs::cam::uin/10002:uin/10002", // 10002 是 uin(帐号ID)
+            //         },
+            //         "Permission": "READ"
+            //     }]
+            // }
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function getObjectAcl() {
+        cos.getObjectAcl({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteObject() {
+        cos.deleteObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '1mb.zip'
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function deleteMultipleObject() {
+        cos.deleteMultipleObject({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Objects: [
+                {Key: '中文/中文.txt'},
+                {Key: '中文/中文.zip'},
+            ]
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function abortUploadTask() {
+        cos.abortUploadTask({
+            Bucket: config.Bucket, /* 必须 */ // Bucket 格式:test-1250000000
+            Region: config.Region, /* 必须 */
+            // 格式1,删除单个上传任务
+            // Level: 'task',
+            // Key: '10mb.zip',
+            // UploadId: '14985543913e4e2642e31db217b9a1a3d9b3cd6cf62abfda23372c8d36ffa38585492681e3',
+            // 格式2,删除单个文件所有未完成上传任务
+            Level: 'file',
+            Key: '10mb.zip',
+            // 格式3,删除 Bucket 下所有未完成上传任务
+            // Level: 'bucket',
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function sliceUploadFile() {
+        var blob = util.createFile({size: 1024 * 1024 * 3});
+        cos.sliceUploadFile({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: '3mb.zip', /* 必须 */
+            Body: blob,
+            TaskReady: function (tid) {
+                TaskId = tid;
+            },
+            onHashProgress: function (progressData) {
+                logger.log('onHashProgress', JSON.stringify(progressData));
+            },
+            onProgress: function (progressData) {
+                logger.log('onProgress', JSON.stringify(progressData));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function selectFileToUpload() {
+        var input = document.createElement('input');
+        input.type = 'file';
+        input.onchange = function (e) {
+            var file = this.files[0];
+            if (file) {
+                if (file.size > 1024 * 1024) {
+                    cos.sliceUploadFile({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: file.name,
+                        Body: file,
+                        TaskReady: function (tid) {
+                            TaskId = tid;
+                        },
+                        onHashProgress: function (progressData) {
+                            logger.log('onHashProgress', JSON.stringify(progressData));
+                        },
+                        onProgress: function (progressData) {
+                            logger.log('onProgress', JSON.stringify(progressData));
+                        },
+                    }, function (err, data) {
+                        logger.log(err || data);
+                    });
+                } else {
+                    cos.putObject({
+                        Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                        Region: config.Region,
+                        Key: file.name,
+                        Body: file,
+                        TaskReady: function (tid) {
+                            TaskId = tid;
+                        },
+                        onProgress: function (progressData) {
+                            logger.log(JSON.stringify(progressData));
+                        },
+                    }, function (err, data) {
+                        logger.log(err || data);
+                    });
+                }
+            }
+        };
+        input.click();
+    }
+
+    function cancelTask() {
+        cos.cancelTask(TaskId);
+        logger.log('canceled');
+    }
+
+    function pauseTask() {
+        cos.pauseTask(TaskId);
+        logger.log('paused');
+    }
+
+    function restartTask() {
+        cos.restartTask(TaskId);
+        logger.log('restart');
+    }
+
+    function uploadFiles() {
+        var filename = 'mb.zip';
+        var blob = util.createFile({size: 1024 * 1024 * 10});
+        cos.uploadFiles({
+            files: [{
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '1' + filename,
+                Body: blob,
+            }, {
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '2' + filename,
+                Body: blob,
+            }, {
+                Bucket: config.Bucket, // Bucket 格式:test-1250000000
+                Region: config.Region,
+                Key: '3' + filename,
+                Body: blob,
+            }],
+            SliceSize: 1024 * 1024,
+            onProgress: function (info) {
+                var percent = parseInt(info.percent * 10000) / 100;
+                var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+                logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+            },
+            onFileFinish: function (err, data, options) {
+                logger.log(options.Key + ' 上传' + (err ? '失败' : '完成'));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    function sliceCopyFile() {
+        // 创建测试文件
+        var sourceName = '3mb.zip';
+        var Key = '3mb.copy.zip';
+
+        var sourcePath = config.Bucket + '.cos.' + config.Region + '.myqcloud.com/'+ encodeURIComponent(sourceName).replace(/%2F/g, '/');
+
+        cos.sliceCopyFile({
+            Bucket: config.Bucket, // Bucket 格式:test-1250000000
+            Region: config.Region,
+            Key: Key,
+            CopySource: sourcePath,
+            SliceSize: 2 * 1024 * 1024, // 大于2M的文件用分片复制,小于则用单片复制
+            onProgress:function (info) {
+                var percent = parseInt(info.percent * 10000) / 100;
+                var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+                logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+            }
+        },function (err,data) {
+            if(err){
+                logger.log(err);
+            }else{
+                logger.log(data);
+            }
+        });
+
+    }
+
+    var time0 = Date.now();
+    var preMsg = '页面加载完成';
+    var showTime = function (msg) {
+        var time1 = Date.now();
+        console.log(preMsg + '->' + msg, time1 - time0);
+        preMsg = msg;
+        time0 = time1;
+    };
+
+    var files;
+    function selectUploadFiles() {
+        showTime('弹出选文件窗口');
+        var input = document.createElement('input');
+        input.type = 'file';
+        input.multiple = true;
+        input.onchange = function (e) {
+            files = this.files;
+            showTime('选完文件');
+        };
+        input.click();
+    }
+    function startSelectUploadFiles() {
+        files.length && cos.uploadFiles({
+            files: [].map.call(files, function (file) {
+                return {
+                    Bucket: config.Bucket,
+                    Region: config.Region,
+                    Key: file.name,
+                    Body: file,
+                };
+            }),
+            SliceSize: 1024 * 1024,
+            onProgress: function (info) {
+                var percent = parseInt(info.percent * 10000) / 100;
+                var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+                logger.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+            },
+            onFileFinish: function (err, data, options) {
+                logger.log(options.Key + ' 上传' + (err ? '失败' : '完成'));
+            },
+        }, function (err, data) {
+            logger.log(err || data);
+        });
+    }
+
+    (function () {
+        var list = [
+            // 'getService', // 不支持
+            'getAuth',
+            'getObjectUrl',
+            // 'putBucket', // 不支持
+            'getBucket',
+            'headBucket',
+            'putBucketAcl',
+            'getBucketAcl',
+            'putBucketCors',
+            'getBucketCors',
+            // 'deleteBucketCors', // 不提供
+            'getBucketLocation',
+            'getBucketLifecycle',
+            'putBucketLifecycle',
+            'deleteBucketLifecycle',
+            'deleteBucket',
+            'putObject',
+            'putObjectCopy',
+            'getObject',
+            'headObject',
+            'putObjectAcl',
+            'getObjectAcl',
+            'deleteObject',
+            'deleteMultipleObject',
+            'abortUploadTask',
+            'sliceUploadFile',
+            'selectFileToUpload',
+            'cancelTask',
+            'pauseTask',
+            'restartTask',
+            'uploadFiles',
+            'selectUploadFiles',
+            'startSelectUploadFiles',
+        ];
+        var container = document.querySelector('.main');
+        var html = [];
+        list.forEach(function (name) {
+            html.push('<a href="javascript:void(0)">' + name + '</a>');
+        });
+        container.innerHTML = html.join('');
+        container.onclick = function (e) {
+            if (e.target.tagName === 'A') {
+                var name = e.target.innerText.trim();
+                window[name]();
+            }
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 80 - 0
node_modules/cos-js-sdk-v5/csp/start.md

@@ -0,0 +1,80 @@
+# COS JavaScript SDK CSP 快速入门
+
+### SDK 获取
+
+对象存储服务的 XML JS SDK 资源 github 地址:[tencentyun/cos-js-sdk-v5](https://github.com/tencentyun/cos-js-sdk-v5)。
+
+演示示例 Demo 代码地址:[XML JS SDK CSP Demo](https://github.com/tencentyun/cos-js-sdk-v5/tree/master/csp/csp.html)。
+
+### 开发准备
+
+1. 首先,JS SDk 需要浏览器支持基本的 HTML5 特性,以便支持 ajax 上传文件和计算文件 md5 值。
+2. 到COS 对象存储控制台创建存储桶,得到 Bucket(存储桶名称) 和 Region(地域名称)
+3. 到控制台密钥管理获取您的项目 SecretId 和 SecretKey。
+4. 配置 CORS 规则,配置例子如下图:
+
+![cors](../demo/cors.png)
+
+> 关于文章中出现的 SecretId、SecretKey、Bucket 等名称的含义和获取方式请参考:[COS 术语信息](https://cloud.tencent.com/document/product/436/7751)
+
+## 快速入门
+### 计算签名
+
+由于签名计算放在前端会暴露 SecretId 和 SecretKey,我们把签名计算过程放在后端实现,前段通过 ajax 向后端获取签名结果,正式部署时请再后端加一层自己网站本身的权限检验。其他语言,请参照对应的 [XML SDK](https://cloud.tencent.com/document/product/436/6474) 文档。
+
+
+### 上传例子
+
+1. 创建 test.html,填入下面的代码,修改里面的 Bucket 和 Region。
+2. 部署好后端的签名服务,并修改 getAuthorization 里的签名服务地址。
+3. 把 test.html 放在 Web 服务器下,然后在浏览器访问页面,测试文件上传。
+
+```html
+<input id="file-selector" type="file">
+<script src="dist/cos-js-sdk-v5.min.js"></script>
+<script>
+var Bucket = 'test-1250000000';
+var Region = 'ap-guangzhou';
+
+// 初始化实例
+var cos = new COS({
+    CompatibilityMode: true,
+    ServiceDomain: 'http://cos.default.xxx.com', // 这里替换成 getService 域名
+    Domain: 'http://{Bucket}.cos.{Region}.xxx.com', // 这里替换成 API 域名格式模板
+    getAuthorization: function (options, callback) {
+        var url = './auth-json.php?method=' + options.Method + '&path=' + encodeURIComponent('/' + options.Key);
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', url, true);
+        xhr.onload = function (e) {
+            callback(e.target.responseText);
+        };
+        xhr.send();
+    },
+});
+
+// 监听选文件
+document.getElementById('file-selector').onchange = function () {
+    
+    var file = this.files[0];
+    if (!file) return;
+
+    // 分片上传文件
+    cos.sliceUploadFile({
+        Bucket: Bucket,
+        Region: Region,
+        Key: file.name,
+        Body: file,
+    }, function (err, data) {
+        console.log(err, data);
+    });
+
+};
+</script>
+```
+
+## webpack 引入方式
+
+支持 webpack 打包的场景,可以用 npm 引入作为模块
+```shell
+npm i cos-js-sdk-v5 --save
+```

Разница между файлами не показана из-за своего большого размера
+ 1603 - 0
node_modules/cos-js-sdk-v5/csp/test.html


+ 40 - 0
node_modules/cos-js-sdk-v5/demo/common/async.js

@@ -0,0 +1,40 @@
+var eachLimit = function (arr, limit, iterator, callback) {
+    callback = callback || function () {};
+    if (!arr.length || limit <= 0) {
+        return callback();
+    }
+
+    var completed = 0;
+    var started = 0;
+    var running = 0;
+
+    (function replenish () {
+        if (completed >= arr.length) {
+            return callback();
+        }
+
+        while (running < limit && started < arr.length) {
+            started += 1;
+            running += 1;
+            iterator(arr[started - 1], function (err) {
+
+                if (err) {
+                    callback(err);
+                    callback = function () {};
+                } else {
+                    completed += 1;
+                    running -= 1;
+                    if (completed >= arr.length) {
+                        callback();
+                    } else {
+                        replenish();
+                    }
+                }
+            });
+        }
+    })();
+};
+
+var Async = {
+    eachLimit: eachLimit,
+};

Разница между файлами не показана из-за своего большого размера
+ 155 - 0
node_modules/cos-js-sdk-v5/demo/common/cos-auth.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/cos-js-sdk-v5/demo/common/cos-auth.min.js


Разница между файлами не показана из-за своего большого размера
+ 2 - 0
node_modules/cos-js-sdk-v5/demo/common/jquery-3.3.1.min.js


Разница между файлами не показана из-за своего большого размера
+ 29 - 0
node_modules/cos-js-sdk-v5/demo/common/lodash.core.min.js


Разница между файлами не показана из-за своего большого размера
+ 6 - 0
node_modules/cos-js-sdk-v5/demo/common/vue.min.js


BIN
node_modules/cos-js-sdk-v5/demo/cors.png


+ 53 - 0
node_modules/cos-js-sdk-v5/demo/crc64.html

@@ -0,0 +1,53 @@
+
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>CRC64</title>
+    <style>
+        h1 {
+            font-weight: normal;
+        }
+    </style>
+</head>
+<body>
+
+<div>
+    <h1>JS 计算 CRC64</h1>
+    <form id="form">
+        <label>选择文件,计算 crc64:</label>
+        <input id="file" type="file">
+    </form>
+    <div id="msg"></div>
+</div>
+
+<script src="./crc64.js"></script>
+<script>
+    var el = function (id) {
+        return document.getElementById(id);
+    };
+    var calc = function (file) {
+        var time0 = Date.now();
+        CRC64.file_crc64(file, function (err, hash) {
+            if (err) return console.log('crc64 error:', err);
+            var time1 = Date.now();
+            el('msg').innerHTML = 'cost ' + (time1 - time0) + 'ms, crc64=' + hash;
+            el('form').reset();
+        }, function (percent) {
+            el('msg').innerHTML = (percent * 100).toFixed(2) + '%';
+        });
+    };
+    el('file').onchange = function () {
+        var file = this.files[0];
+        calc(file);
+    };
+
+    // calc string crc64
+    console.log(CRC64.crc64('123456789'));
+</script>
+
+</body>
+</html>

Разница между файлами не показана из-за своего большого размера
+ 17990 - 0
node_modules/cos-js-sdk-v5/demo/crc64.js


Разница между файлами не показана из-за своего большого размера
+ 1890 - 0
node_modules/cos-js-sdk-v5/demo/demo.js


+ 1 - 0
node_modules/cos-js-sdk-v5/demo/empty.html

@@ -0,0 +1 @@
+This is a helper for "simple-form.html".

+ 19 - 0
node_modules/cos-js-sdk-v5/demo/folder/index.html

@@ -0,0 +1,19 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>COS 文件管理</title>
+    <link rel="stylesheet" href="style.css">
+</head>
+<body>
+
+<div class="page">
+    <h1>COS 文件管理</h1>
+    <div id="app">待实现...</div>
+</div>
+
+</body>
+</html>

+ 38 - 0
node_modules/cos-js-sdk-v5/demo/index.html

@@ -0,0 +1,38 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>cos-js-sdk-v5</title>
+    <style>
+        body { font-family: "Microsoft YaHei";}
+        .page { min-width:1000px; margin:0 auto; padding: 0 50px;}
+        .main-wrap { float: left; width: 100%; }
+        .main { margin-right: 700px; margin-bottom: 20px; }
+        .siderbar { float: left; width: 600px; margin-left: -600px; margin-bottom: 20px; padding-top: 60px }
+        .result { line-height:1.3;font-size: 13px;font-family:monospace;border:1px solid #006eff;margin:0;height:200px;overflow:auto;box-sizing:border-box;padding:5px;}
+        h1 { font-weight: normal; color:#333;}
+        a { color: #006eff; background-color: transparent; padding: 8px 16px; line-height: 1.3; display: inline-block; text-align: center; margin: 0 8px 8px 0; border: 1px solid #006eff; font-size: 14px; text-decoration: none; }
+        a:hover { color: #fff; background-color: #006eff; }
+        hr {border: 0; border-top: 1px solid #006eff;}
+    </style>
+</head>
+<body>
+
+<div class="page">
+    <h1>cos-js-sdk-v5</h1>
+    <div class="main-wrap">
+        <div class="main"></div>
+    </div>
+    <div class="siderbar">
+        <pre class="result"></pre>
+    </div>
+</div>
+
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script src="./demo.js"></script>
+
+</body>
+</html>

+ 101 - 0
node_modules/cos-js-sdk-v5/demo/mime-limit.html

@@ -0,0 +1,101 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>上传限制 Content-Type</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>上传限制 Content-Type</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="submit">
+
+<div id="msg"></div>
+
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script>
+    (function () {
+        // 计算签名
+        var getUploadSign = function (options, callback) {
+            var url = '/uploadSign?filename=' + encodeURIComponent(options.filename) + '&_=' + Date.now();
+            var xhr = new XMLHttpRequest();
+            xhr.open('POST', url, true);
+            xhr.onload = function (e) {
+                var token;
+                try {
+                    token = (new Function('return ' + xhr.responseText))();
+                } catch (e) {}
+                if (token) {
+                    callback(null, token);
+                } else {
+                    console.error(xhr.responseText);
+                    callback('获取签名出错');
+                }
+            };
+            xhr.onerror = function (e) {
+                callback('获取签名出错');
+            };
+            xhr.send();
+        };
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            getUploadSign({ filename: file.name }, function (err, info) {
+                if (err) {
+                    alert(err);
+                    return;
+                }
+                var signMap = info.signMap;
+                var mimeLimit = info.mimeLimit;
+                var allowActions = ['ListMultipartUploads', 'ListParts', 'InitiateMultipartUpload', 'UploadPart', 'CompleteMultipartUpload', 'PutObject'];
+                var cos = new COS({
+                    getAuthorization: function (opt, cb) {
+                        var action = opt.Scope[0].action.split(':')[1];
+                        if (allowActions.indexOf(action) === -1) return console.error('action not allow');
+                        var auth = signMap[action];
+                        cb({ Authorization: auth });
+                    },
+                });
+                cos.uploadFile({
+                    Bucket: info.bucket,
+                    Region: info.region,
+                    Key: info.key,
+                    Body: file,
+                    SliceSize: 1024 * 1024 * 8,
+                    ChunkSize: 1024 * 1024 * 8,
+                    Headers: {
+                        'x-cos-mime-limit': mimeLimit,
+                    },
+                }, function (err, data) {
+                    callback(err, data);
+                });
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? '上传失败:' + err.code + '(' + err.message + ')' : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 144 - 0
node_modules/cos-js-sdk-v5/demo/policy-form.html

@@ -0,0 +1,144 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Form 表单简单上传</title>
+    <style>h1, h2 {font-weight: normal;}#msg {margin-top:10px;}</style>
+</head>
+<body>
+
+<h1>PostObject 上传(Policy 保护,Form 表单上传)</h1>
+<div>最低兼容到 IE6 上传,使用 policy 签名保护,不支持 onprogress</div>
+
+<form id="form" target="submitTarget" action="" method="post" enctype="multipart/form-data" accept="*/*">
+    <!-- file 字段放在表单最后,避免文件内容过长影响签名判断和鉴权 -->
+    <input id="fileSelector" name="file" type="file">
+    <input id="submitBtn" type="button" value="提交">
+</form>
+<iframe id="submitTarget" name="submitTarget" style="display:none;" frameborder="0"></iframe>
+
+<div id="msg"></div>
+
+<script src="common/cos-auth.min.js"></script>
+<script>
+    (function () {
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
+        var prefix = protocol + '//' + Bucket + '.cos.' + Region + '.myqcloud.com/';
+        var fileSelector = document.getElementById('fileSelector');
+        var form = document.getElementById('form');
+        form.action = prefix;
+
+        // 对更多字符编码的 url encode 格式
+        var camSafeUrlEncode = function (str) {
+            return encodeURIComponent(str)
+                .replace(/!/g, '%21')
+                .replace(/'/g, '%27')
+                .replace(/\(/g, '%28')
+                .replace(/\)/g, '%29')
+                .replace(/\*/g, '%2A');
+        };
+
+        // 获取权限策略
+        var getPostPolicyCredentials = function (opt, callback) {
+            var url = 'http://127.0.0.1:3000/post-policy?key=' + encodeURIComponent(opt.Key);
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onreadystatechange = function (e) {
+                if (xhr.readyState === 4) {
+                    if (xhr.status === 200) {
+                        var credentials;
+                        try {
+                            credentials = (new Function('return ' + xhr.responseText))();
+                        } catch (e) {}
+                        if (credentials) {
+                            callback(null, credentials);
+                        } else {
+                            console.error(xhr.responseText);
+                            callback('获取签名出错');
+                        }
+                    } else {
+                        callback('获取签名出错');
+                    }
+                }
+            };
+            xhr.send();
+        };
+
+        // 监听上传完成
+        var Key;
+        var submitTarget = document.getElementById('submitTarget');
+        var showMessage = function (err, data) {
+            console.log(err || data);
+            document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+        };
+        submitTarget.onload = function () {
+            var search;
+            try {
+                search = submitTarget.contentWindow.location.search.substr(1);
+            } catch (e) {
+                showMessage('文件 ' + Key + ' 上传失败');
+            }
+            if (search) {
+                var items = search.split('&');
+                var i, arr, data = {};
+                for (i = 0; i < items.length; i++) {
+                    arr = items[i].split('=');
+                    data[arr[0]] = decodeURIComponent(arr[1] || '');
+                }
+                showMessage(null, {url: prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/'), ETag: data.etag});
+            } else {
+            }
+        };
+
+        var setFormField = function (key, value) {
+            var el = document.getElementById(key);
+            if (!el) {
+                el = document.createElement('input');
+                el.hidden = true;
+                el.id = key;
+                el.name = key;
+                form.insertBefore(el, fileSelector);
+            }
+            el.setAttribute('value', value); // 需要保证 file 在表单最后
+            el.value = value;
+        };
+
+        // 发起上传
+        document.getElementById('submitBtn').onclick = function (e) {
+            var filePath = document.getElementById('fileSelector').value;
+            if (!filePath) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            Key = 'dir/' + filePath.match(/[\\\/]?([^\\\/]+)$/)[1]; // 这里指定上传目录和文件名
+
+            // 获取签名保护字段
+            getPostPolicyCredentials({
+                Key: Key,
+            }, function (err, credentials) {
+
+                // 在当前目录下放一个空的 empty.html 以便让接口上传完成跳转回来
+                setFormField('success_action_redirect', location.href.substr(0, location.href.lastIndexOf('/') + 1) + 'empty.html');
+                setFormField('key', Key);
+
+                // 使用 policy 签名保护格式
+                credentials.securityToken && setFormField('x-cos-security-token', credentials.securityToken);
+                setFormField('q-sign-algorithm', credentials.qSignAlgorithm);
+                setFormField('q-ak', credentials.qAk);
+                setFormField('q-key-time', credentials.qKeyTime);
+                setFormField('q-signature', credentials.qSignature);
+                setFormField('policy', credentials.policy);
+
+                // 提交表单
+                form.submit();
+
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 137 - 0
node_modules/cos-js-sdk-v5/demo/policy-post.html

@@ -0,0 +1,137 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Ajax Post 上传</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>PostObject 上传(Policy 保护,Ajax POST 请求)</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="submit">
+
+<div id="msg"></div>
+
+<script src="common/cos-auth.min.js"></script>
+<script>
+    (function () {
+
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
+        var prefix = protocol + '//' + Bucket + '.cos.' + Region + '.myqcloud.com/';
+
+        // 对更多字符编码的 url encode 格式
+        var camSafeUrlEncode = function (str) {
+            return encodeURIComponent(str)
+                .replace(/!/g, '%21')
+                .replace(/'/g, '%27')
+                .replace(/\(/g, '%28')
+                .replace(/\)/g, '%29')
+                .replace(/\*/g, '%2A');
+        };
+
+        // 获取权限策略
+        var getPostPolicyCredentials = function (opt, callback) {
+            var url = 'http://127.0.0.1:3000/post-policy?key=' + encodeURIComponent(opt.Key);
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onreadystatechange = function (e) {
+                if (xhr.readyState === 4) {
+                    if (xhr.status === 200) {
+                        var credentials;
+                        try {
+                            credentials = (new Function('return ' + xhr.responseText))();
+                        } catch (e) {}
+                        if (credentials) {
+                            callback(null, credentials);
+                        } else {
+                            console.error(xhr.responseText);
+                            callback('获取签名出错');
+                        }
+                    } else {
+                        callback('获取签名出错');
+                    }
+                }
+            };
+            xhr.send();
+        };
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            var Key = 'dir/' + file.name; // 这里指定上传目录和文件名
+            getPostPolicyCredentials({
+                Bucket: Bucket,
+                Key: Key,
+                ACL: 'default'
+            }, function (err, credentials) {
+                var fd = new FormData();
+
+                // 在当前目录下放一个空的 empty.html 以便让接口上传完成跳转回来
+                fd.append('key', Key);
+
+                // // 使用普通签名格式
+                // fd.append('Signature', credentials.Authorization);
+                // fd.append('x-cos-security-token', credentials.SecurityToken || '');
+
+                // 使用 policy 签名保护格式
+                credentials.securityToken && fd.append('x-cos-security-token', credentials.securityToken);
+                fd.append('q-sign-algorithm', credentials.qSignAlgorithm);
+                fd.append('q-ak', credentials.qAk);
+                fd.append('q-key-time', credentials.qKeyTime);
+                fd.append('q-signature', credentials.qSignature);
+                fd.append('policy', credentials.policy);
+
+                // 文件内容,file 字段放在表单最后,避免文件内容过长影响签名判断和鉴权
+                fd.append('file', file);
+
+                // xhr
+                var url = prefix;
+                var xhr = new XMLHttpRequest();
+                xhr.open('POST', url, true);
+                xhr.upload.onprogress = function (e) {
+                    console.log('上传进度 ' + (Math.round(e.loaded / e.total * 10000) / 100) + '%');
+                };
+                xhr.onload = function () {
+                    if (Math.floor(xhr.status / 100) === 2) {
+                        var ETag = xhr.getResponseHeader('etag');
+                        callback(null, {url: prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/'), ETag: ETag});
+                    } else {
+                        callback('文件 ' + Key + ' 上传失败,状态码:' + xhr.status);
+                    }
+                };
+                xhr.onerror = function () {
+                    callback('文件 ' + Key + ' 上传失败,请检查是否没配置 CORS 跨域规则');
+                };
+                xhr.send(fd);
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 66 - 0
node_modules/cos-js-sdk-v5/demo/queue/index.html

@@ -0,0 +1,66 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>COS 上传队列</title>
+    <link rel="stylesheet" href="style.css">
+</head>
+<body>
+
+<div class="page">
+    <h1>COS 上传队列</h1>
+    <div id="app">
+        <form id="form">
+            <div class="float-right">共{{total}}个文件</div>
+            <input type="file" value="选择上传文件" multiple @change="selectedFile">
+        </form>
+        <table class="file-list">
+            <colgroup>
+                <col style="width:20%;">
+                <col style="width:10%;">
+                <col style="width:40%;">
+                <col style="width:30%;">
+            </colgroup>
+            <tr class="file-item">
+                <td>文件名</td>
+                <td>大小</td>
+                <td>进度</td>
+                <td class="file-action">操作</td>
+            </tr>
+            <tr class="file-item" v-for="item in list">
+                <td><span class="file-name">{{item.Key}}</span></td>
+                <td>{{formatSize(item.size)}}</td>
+                <td>
+                    <span class="file-progress" v-if="item.state==='uploading'">
+                        <span class="file-progress-loaded" :style="'width:'+item.percent*100+'%'"></span>
+                    </span>
+                    <span v-if="item.state==='success'">已完成</span>
+                    <span v-else-if="item.state==='waiting'">等待上传</span>
+                    <span v-else-if="item.state==='checking'">校验中({{parseInt(item.hashPercent*100)}}%)</span>
+                    <span v-else-if="item.state==='paused'">已暂停, 已传{{formatSize(item.loaded)}}</span>
+                    <span v-else-if="item.state==='canceled'">已取消</span>
+                    <span v-else>{{formatSize(item.speed)}}/s, 已传{{formatSize(item.loaded)}} {{parseInt(item.percent*100)}}%</span>
+                </td>
+                <td class="file-action">
+                    <a v-if="['waiting','checking','uploading'].includes(item.state)" href="javascript:void(0)" @click="pauseTask(item)">暂停</a>
+                    <a v-if="['error','paused'].includes(item.state)" href="javascript:void(0)" @click="restartTask(item)">开始</a>
+                    <a v-if="item.state!=='canceled'" href="javascript:void(0)" @click="cancelTask(item)">删除</a>
+                </td>
+            </tr>
+            <tr class="file-item" v-if="!list.length">
+                <td colspan="4" align="center">暂无上传文件</td>
+            </tr>
+        </table>
+    </div>
+</div>
+
+<script src="../../dist/cos-js-sdk-v5.js"></script>
+<script src="../common/lodash.core.min.js"></script>
+<script src="../common/vue.min.js"></script>
+<script src="./index.js"></script>
+
+</body>
+</html>

+ 77 - 0
node_modules/cos-js-sdk-v5/demo/queue/index.js

@@ -0,0 +1,77 @@
+var Bucket = 'test-1250000000';
+var Region = 'ap-guangzhou';
+
+var cos = new COS({
+    FileParallelLimit: 5,
+    ChunkParallelLimit: 5,
+    ChunkMbSize: 8 * 1024 * 1024,
+    getAuthorization: function (options, callback) {
+        var url = '/sts';
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', url, true);
+        xhr.onload = function (e) {
+            try {
+                var data = JSON.parse(e.target.responseText);
+            } catch (e) {
+            }
+            callback({
+                TmpSecretId: data.credentials && data.credentials.tmpSecretId,
+                TmpSecretKey: data.credentials && data.credentials.tmpSecretKey,
+                SecurityToken: data.credentials && data.credentials.sessionToken,
+                ExpiredTime: data.expiredTime
+            });
+        };
+        xhr.send();
+    }
+});
+
+new Vue({
+    el: '#app',
+    data: function () {
+        return {
+            FileParallelLimit: 5,
+            ChunkParallelLimit: 16,
+            ChunkMbSize: 2,
+            list: [],
+            total: 0,
+        };
+    },
+    created: function () {
+        var self = this;
+        cos.on('list-update', function (data) {
+            self.list = data.list;
+            self.total = data.list.length;
+        });
+    },
+    methods: {
+        formatSize: function (size) {
+            var i, unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
+            for (i = 0; i < unit.length && size >= 1024; i++) {
+                size /= 1024;
+            }
+            return (Math.round(size * 100) / 100 || 0) + unit[i];
+        },
+        selectedFile: function (e) {
+            var files = e.target.files;
+            var list = [].map.call(files, function (f) {
+                return {
+                    Bucket: Bucket,
+                    Region: Region,
+                    Key: f.name,
+                    Body: f,
+                };
+            });
+            cos.uploadFiles({files: list});
+            document.getElementById('form').reset();
+        },
+        pauseTask: function (task) {
+            cos.pauseTask(task.id);
+        },
+        restartTask: function (task) {
+            cos.restartTask(task.id);
+        },
+        cancelTask: function (task) {
+            cos.cancelTask(task.id);
+        },
+    },
+});

+ 78 - 0
node_modules/cos-js-sdk-v5/demo/queue/style.css

@@ -0,0 +1,78 @@
+h1 {
+    font-family: "Microsoft YaHei";
+    font-weight: normal;
+}
+
+ul,
+li {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+
+a {
+    color: #0071ff;
+}
+
+.float-right {
+    float: right;
+}
+
+.page {
+    width: 960px;
+    margin: 0 auto;
+    font-size: 14px;
+}
+
+#form input[type="text"] {
+    width: 40px;
+    padding: 2px;
+    vertical-align: middle;
+}
+#form input[type="file"] {
+    vertical-align: middle;
+}
+
+.file-list {
+    margin-top: 20px;
+    width: 100%;
+}
+
+.file-list {
+    width: 960px;
+    border-collapse: collapse;
+}
+
+.file-name {
+    display: inline-block;
+    width: 310px;
+    text-overflow: ellipsis;
+    white-space: nowrap
+}
+
+.file-item td {
+    border: 1px solid #ccc;
+    padding: 5px 10px;
+    font-size: 12px;
+    line-height: 20px;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap
+}
+
+.file-progress {
+    position: relative;
+    display: inline-block;
+    width: 100px;
+    height: 6px;
+    background: #ddd;
+    vertical-align: middle;
+    margin-right: 5px;
+}
+
+.file-progress-loaded {
+    position: absolute;
+    display: inline-block;
+    height: 6px;
+    background: #0071ff;
+}

+ 170 - 0
node_modules/cos-js-sdk-v5/demo/slice-task.html

@@ -0,0 +1,170 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>自定义的分片上传</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>自定义的分片上传</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="button" value="上传文件">
+<input id="cancelBtn" type="button" value="取消最后一个上传文件">
+
+<div id="msg"></div>
+
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script src="./common/async.js"></script>
+<script>
+    (function () {
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var ChunkSize = 1024 * 1024 * 8;
+
+        // 初始化 SDK
+        var cos = new COS({
+            getAuthorization: function (options, callback) {
+                var url = '/sts'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
+                var xhr = new XMLHttpRequest();
+                xhr.open('GET', url, true);
+                xhr.onload = function (e) {
+                    try {
+                        var data = JSON.parse(e.target.responseText);
+                        var credentials = data.credentials;
+                    } catch (e) {
+                    }
+                    if (!data || !credentials) return console.error('credentials invalid');
+                    callback({
+                        TmpSecretId: credentials.tmpSecretId,
+                        TmpSecretKey: credentials.tmpSecretKey,
+                        SecurityToken: credentials.sessionToken,
+                        StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
+                        ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000900
+                    });
+                };
+                xhr.send();
+            },
+        });
+        var uuid = function () {
+            var S4 = function () {
+                return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+            };
+            return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+        };
+
+        // 外部维护上传任务状态
+        var lastTaskId;
+        var taskStateMap = {};
+        cos._isRunningTask = function (tid) {
+            return taskStateMap[tid] === 'uploading';
+        };
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            var TaskId = lastTaskId = uuid();
+            taskStateMap[TaskId] = 'uploading';
+            var fileSize = file.size;
+            var Key = 'dir/' + file.name; // 这里指定上传目录和文件名
+            console.log('上传任务已开始:' + lastTaskId, TaskId, Key);
+            // 创建 UploadId
+            cos.multipartInit({
+                Bucket: Bucket,
+                Region: Region,
+                Key: Key,
+            }, function (err, data) {
+                if (!cos._isRunningTask(TaskId)) return;
+                if (err) {
+                    taskStateMap[TaskId] = 'error';
+                    return console.error('UploadId 创建出错:', err);
+                }
+                var UploadId = data.UploadId;
+                console.log('UploadId 已创建:', UploadId);
+                var Parts = new Array(Math.ceil(fileSize / ChunkSize)).fill(0).map(function (item, index) {
+                    return {PartNumber: index + 1};
+                });
+                Async.eachLimit(Parts, 3, function (partItem, nextPart) {
+                    if (!cos._isRunningTask(TaskId)) return;
+                    var PartNumber = partItem.PartNumber;
+                    var start = (PartNumber - 1) * ChunkSize;
+                    var end = Math.min(start + ChunkSize);
+                    var blob = file.slice(start, end);
+                    // 上传每个分片
+                    cos.multipartUpload({
+                        Task: lastTaskId,
+                        Bucket: Bucket,
+                        Region: Region,
+                        Key: Key,
+                        UploadId: UploadId,
+                        PartNumber: PartNumber,
+                        Body: blob,
+                    }, function (err, data) {
+                        if (!cos._isRunningTask(TaskId)) return;
+                        if (err) return nextPart(err);
+                        if (!data.headers.etag) return nextPart('浏览器获取不到 ETag Header,需要存储桶配置 CORS ExposeHeaders 允许当前域名跨域读取 ETag 字段。');
+                        partItem.ETag = data.headers.etag || '';
+                        console.log('分片上传完成:', partItem.PartNumber, partItem.ETag);
+                        nextPart();
+                    });
+                }, function (err) {
+                    if (!cos._isRunningTask(TaskId)) return;
+                    if (err) {
+                        taskStateMap[TaskId] = 'error';
+                        return console.error('上传分片出错:', err);
+                    }
+                    // 完成分片上传
+                    cos.multipartComplete({
+                        Bucket: Bucket,
+                        Region: Region,
+                        Key: Key,
+                        UploadId: UploadId,
+                        Parts: Parts,
+                    }, function (err, data) {
+                        if (err) {
+                            taskStateMap[TaskId] = 'error';
+                            return console.error('文件完成出错:', err);
+                        }
+                        console.log('文件上传成功:', data.Location);
+                        taskStateMap[TaskId] = 'success';
+                        callback(err, data);
+                    });
+                });
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+
+        // 监听取消上传
+        document.getElementById('cancelBtn').onclick = function (e) {
+            // 标记任务取消,让 SDK 外部的上传流程停止
+            taskStateMap[lastTaskId] = 'canceled';
+            // 取消 SDK 正在执行的 xhr 上传请求,触发 xhr.abort()
+            cos.cancelTask(lastTaskId);
+            console.log('上传任务已取消:' + lastTaskId);
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 129 - 0
node_modules/cos-js-sdk-v5/demo/slice.html

@@ -0,0 +1,129 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>自定义的分片上传</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>自定义的分片上传</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="submit">
+
+<div id="msg"></div>
+
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script src="./common/async.js"></script>
+<script>
+    (function () {
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var ChunkSize = 1024 * 1024 * 8;
+
+        // 初始化 SDK
+        var cos = new COS({
+            getAuthorization: function (options, callback) {
+                var url = '/sts'; // 如果是 npm run sts.js 起的 nodejs server,使用这个
+                var xhr = new XMLHttpRequest();
+                xhr.open('GET', url, true);
+                xhr.onload = function (e) {
+                    try {
+                        var data = JSON.parse(e.target.responseText);
+                        var credentials = data.credentials;
+                    } catch (e) {
+                    }
+                    if (!data || !credentials) return console.error('credentials invalid');
+                    callback({
+                        TmpSecretId: credentials.tmpSecretId,
+                        TmpSecretKey: credentials.tmpSecretKey,
+                        SecurityToken: credentials.sessionToken,
+                        StartTime: data.startTime, // 时间戳,单位秒,如:1580000000,建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
+                        ExpiredTime: data.expiredTime, // 时间戳,单位秒,如:1580000900
+                    });
+                };
+                xhr.send();
+            },
+        });
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            var fileSize = file.size;
+            var Key = 'dir/' + file.name; // 这里指定上传目录和文件名
+            // 创建 UploadId
+            cos.multipartInit({
+                Bucket: Bucket,
+                Region: Region,
+                Key: Key,
+            }, function (err, data) {
+                if (err) return console.error('UploadId 创建出错:', err);
+                var UploadId = data.UploadId;
+                console.log('UploadId 已创建:', UploadId);
+                var Parts = new Array(Math.ceil(fileSize / ChunkSize)).fill(0).map(function (item, index) {
+                    return {PartNumber: index + 1};
+                });
+                Async.eachLimit(Parts, 3, function (partItem, nextPart) {
+                    var PartNumber = partItem.PartNumber;
+                    var start = (PartNumber - 1) * ChunkSize;
+                    var end = Math.min(start + ChunkSize);
+                    var blob = file.slice(start, end);
+                    // 上传每个分片
+                    cos.multipartUpload({
+                        Bucket: Bucket,
+                        Region: Region,
+                        Key: Key,
+                        UploadId: UploadId,
+                        PartNumber: PartNumber,
+                        Body: blob,
+                    }, function (err, data) {
+                        if (err) return nextPart(err);
+                        if (!data.headers.etag) return nextPart('浏览器获取不到 ETag Header,需要存储桶配置 CORS ExposeHeaders 允许当前域名跨域读取 ETag 字段。');
+                        partItem.ETag = data.headers.etag || '';
+                        console.log('分片上传完成:', partItem.PartNumber, partItem.ETag);
+                        nextPart();
+                    });
+                }, function (err) {
+                    if (err) return console.error('上传分片出错:', err);
+                    // 完成分片上传
+                    cos.multipartComplete({
+                        Bucket: Bucket,
+                        Region: Region,
+                        Key: Key,
+                        UploadId: UploadId,
+                        Parts: Parts,
+                    }, function (err, data) {
+                        if (err) return console.error('文件完成出错:', err);
+                        console.log('文件上传成功:', data.Location);
+                        callback(err, data);
+                    });
+                });
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 134 - 0
node_modules/cos-js-sdk-v5/demo/sts-form.html

@@ -0,0 +1,134 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Form 表单简单上传</title>
+    <style>h1, h2 {font-weight: normal;}#msg {margin-top:10px;}</style>
+</head>
+<body>
+
+<h1>Form 表单简单上传(兼容 IE8)</h1>
+<div>最低兼容到 IE6 上传,不支持 onprogress</div>
+
+<form id="form" target="submitTarget" action="" method="post" enctype="multipart/form-data" accept="*/*">
+    <input id="name" name="name" type="hidden" value="">
+    <input name="success_action_status" type="hidden" value="200">
+    <input id="success_action_redirect" name="success_action_redirect" type="hidden" value="">
+    <input id="key" name="key" type="hidden" value="">
+    <input id="Signature" name="Signature" type="hidden" value="">
+    <input name="Content-Type" type="hidden" value="">
+    <input id="x-cos-security-token" name="x-cos-security-token" type="hidden" value="">
+
+    <!-- file 字段放在表单最后,避免文件内容过长影响签名判断和鉴权 -->
+    <input id="fileSelector" name="file" type="file">
+    <input id="submitBtn" type="button" value="提交">
+</form>
+<iframe id="submitTarget" name="submitTarget" style="display:none;" frameborder="0"></iframe>
+
+<div id="msg"></div>
+
+<script src="common/cos-auth.min.js"></script>
+<script>
+    (function () {
+
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
+        var prefix = protocol + '//' + Bucket + '.cos.' + Region + '.myqcloud.com/';
+        var form = document.getElementById('form');
+        form.action = prefix;
+
+        // 对更多字符编码的 url encode 格式
+        var camSafeUrlEncode = function (str) {
+            return encodeURIComponent(str)
+                .replace(/!/g, '%21')
+                .replace(/'/g, '%27')
+                .replace(/\(/g, '%28')
+                .replace(/\)/g, '%29')
+                .replace(/\*/g, '%2A');
+        };
+
+        // 计算签名
+        var getAuthorization = function (options, callback) {
+            // var url = 'http://127.0.0.1:3000/sts';
+            var url = '../server/sts.php';
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onreadystatechange = function (e) {
+                if (xhr.readyState === 4) {
+                    if (xhr.status === 200) {
+                        var credentials;
+                        try {
+                            credentials = (new Function('return ' + xhr.responseText))().credentials;
+                        } catch (e) {}
+                        if (credentials) {
+                            callback(null, {
+                                SecurityToken: credentials.sessionToken,
+                                Authorization: CosAuth({
+                                    SecretId: credentials.tmpSecretId,
+                                    SecretKey: credentials.tmpSecretKey,
+                                    Method: options.Method,
+                                    Pathname: options.Pathname,
+                                })
+                            });
+                        } else {
+                            console.error(xhr.responseText);
+                            callback('获取签名出错');
+                        }
+                    } else {
+                        callback('获取签名出错');
+                    }
+                }
+            };
+            xhr.send();
+        };
+
+        // 监听上传完成
+        var Key;
+        var submitTarget = document.getElementById('submitTarget');
+        var showMessage = function (err, data) {
+            console.log(err || data);
+            document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+        };
+        submitTarget.onload = function () {
+            var search;
+            try {
+                search = submitTarget.contentWindow.location.search.substr(1);
+            } catch (e) {
+                showMessage('文件 ' + Key + ' 上传失败');
+            }
+            if (search) {
+                var items = search.split('&');
+                var i, arr, data = {};
+                for (i = 0; i < items.length; i++) {
+                    arr = items[i].split('=');
+                    data[arr[0]] = decodeURIComponent(arr[1] || '');
+                }
+                showMessage(null, {url: prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/'), ETag: data.etag});
+            } else {
+            }
+        };
+
+        // 发起上传
+        document.getElementById('submitBtn').onclick = function (e) {
+            var filePath = document.getElementById('fileSelector').value;
+            if (!filePath) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            Key = 'dir/' + filePath.match(/[\\\/]?([^\\\/]+)$/)[1]; // 这里指定上传目录和文件名
+            getAuthorization({Method: 'POST', Pathname: '/'}, function (err, AuthData) {
+                // 在当前目录下放一个空的 empty.html 以便让接口上传完成跳转回来
+                document.getElementById('success_action_redirect').value = location.href.substr(0, location.href.lastIndexOf('/') + 1) + 'empty.html';
+                document.getElementById('key').value = Key;
+                document.getElementById('signature').value = AuthData.Authorization;
+                document.getElementById('x-cos-security-token').value = AuthData.SecurityToken || '';
+                form.submit();
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 126 - 0
node_modules/cos-js-sdk-v5/demo/sts-post.html

@@ -0,0 +1,126 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Ajax Post 上传</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>Ajax Post 上传</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="submit">
+
+<div id="msg"></div>
+
+<script src="common/cos-auth.min.js"></script>
+<script>
+    (function () {
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
+        var prefix = protocol + '//' + Bucket + '.cos.' + Region + '.myqcloud.com/';
+
+        // 对更多字符编码的 url encode 格式
+        var camSafeUrlEncode = function (str) {
+            return encodeURIComponent(str)
+                .replace(/!/g, '%21')
+                .replace(/'/g, '%27')
+                .replace(/\(/g, '%28')
+                .replace(/\)/g, '%29')
+                .replace(/\*/g, '%2A');
+        };
+
+        // 计算签名
+        var getAuthorization = function (options, callback) {
+            // var url = 'http://127.0.0.1:3000/sts';
+            var url = '../server/sts.php';
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onreadystatechange = function (e) {
+                if (xhr.readyState === 4) {
+                    if (xhr.status === 200) {
+                        var credentials;
+                        try {
+                            credentials = (new Function('return ' + xhr.responseText))().credentials;
+                        } catch (e) {}
+                        if (credentials) {
+                            callback(null, {
+                                SecurityToken: credentials.sessionToken,
+                                Authorization: CosAuth({
+                                    SecretId: credentials.tmpSecretId,
+                                    SecretKey: credentials.tmpSecretKey,
+                                    Method: options.Method,
+                                    Pathname: options.Pathname,
+                                })
+                            });
+                        } else {
+                            console.error(xhr.responseText);
+                            callback('获取签名出错');
+                        }
+                    } else {
+                        callback('获取签名出错');
+                    }
+                }
+            };
+            xhr.send();
+        };
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            var Key = 'dir/' + file.name; // 这里指定上传目录和文件名
+            getAuthorization({Method: 'POST', Pathname: '/'}, function (err, info) {
+                var fd = new FormData();
+                fd.append('key', Key);
+                fd.append('signature', info.Authorization);
+                fd.append('Content-Type', '');
+                info.SecurityToken && fd.append('x-cos-security-token', info.SecurityToken);
+                fd.append('file', file); // file 字段放在表单最后,避免文件内容过长影响签名判断和鉴权
+                var url = prefix;
+                var xhr = new XMLHttpRequest();
+                xhr.open('POST', url, true);
+                xhr.upload.onprogress = function (e) {
+                    console.log('上传进度 ' + (Math.round(e.loaded / e.total * 10000) / 100) + '%');
+                };
+                xhr.onload = function () {
+                    if (Math.floor(xhr.status / 100) === 2) {
+                        var ETag = xhr.getResponseHeader('etag');
+                        callback(null, {url: prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/'), ETag: ETag});
+                    } else {
+                        callback('文件 ' + Key + ' 上传失败,状态码:' + xhr.status);
+                    }
+                };
+                xhr.onerror = function () {
+                    callback('文件 ' + Key + ' 上传失败,请检查是否没配置 CORS 跨域规则');
+                };
+                xhr.send(fd);
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 129 - 0
node_modules/cos-js-sdk-v5/demo/sts-put-server-key.html

@@ -0,0 +1,129 @@
+
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Ajax Put 上传</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>Ajax Put 上传</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="submit">
+
+<div id="msg"></div>
+
+<script src="common/cos-auth.min.js"></script>
+<script>
+    (function () {
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
+        var prefix = protocol + '//' + Bucket + '.cos.' + Region + '.myqcloud.com/';
+
+        // 对更多字符编码的 url encode 格式
+        var camSafeUrlEncode = function (str) {
+            return encodeURIComponent(str)
+                .replace(/!/g, '%21')
+                .replace(/'/g, '%27')
+                .replace(/\(/g, '%28')
+                .replace(/\)/g, '%29')
+                .replace(/\*/g, '%2A');
+        };
+
+        // 计算签名
+        var getKeyAndAuth = function (options, callback) {
+            var url = 'http://127.0.0.1:3000/sts-server-key';
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onload = function (e) {
+                var result, credentials;
+                try {
+                    result = (new Function('return ' + xhr.responseText))();
+                    credentials = result.credentials;
+                } catch (e) {}
+                if (result && credentials) {
+                    callback(null, {
+                        Key: result.Key, // 这里在后端加一个字段决定上传的文件名
+                        SecurityToken: credentials.sessionToken,
+                        Authorization: CosAuth({
+                            SecretId: credentials.tmpSecretId,
+                            SecretKey: credentials.tmpSecretKey,
+                            Method: options.Method,
+                            Pathname: '/' + options.Key,
+                        }),
+                    });
+                } else {
+                    console.error(xhr.responseText);
+                    callback('获取签名出错');
+                }
+            };
+            xhr.onerror = function (e) {
+                callback('获取签名出错');
+            };
+            xhr.send();
+        };
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            getKeyAndAuth({Method: 'PUT', FileName: file.name}, function (err, info) {
+                var Key = info.Key;
+
+                if (err) {
+                    alert(err);
+                    return;
+                }
+
+                var auth = info.Authorization;
+                var SecurityToken = info.SecurityToken;
+                var url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
+                var xhr = new XMLHttpRequest();
+                xhr.open('PUT', url, true);
+                xhr.setRequestHeader('Authorization', auth);
+                SecurityToken && xhr.setRequestHeader('x-cos-security-token', SecurityToken);
+                xhr.upload.onprogress = function (e) {
+                    console.log('上传进度 ' + (Math.round(e.loaded / e.total * 10000) / 100) + '%');
+                };
+                xhr.onload = function () {
+                    if (xhr.status === 200 || xhr.status === 206) {
+                        var ETag = xhr.getResponseHeader('etag');
+                        callback(null, {url: url, ETag: ETag});
+                    } else {
+                        callback('文件 ' + Key + ' 上传失败,状态码:' + xhr.status);
+                    }
+                };
+                xhr.onerror = function () {
+                    callback('文件 ' + Key + ' 上传失败,请检查是否没配置 CORS 跨域规则');
+                };
+                xhr.send(file);
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

+ 128 - 0
node_modules/cos-js-sdk-v5/demo/sts-put.html

@@ -0,0 +1,128 @@
+
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Ajax Put 上传</title>
+    <style>
+        h1, h2 {
+            font-weight: normal;
+        }
+
+        #msg {
+            margin-top: 10px;
+        }
+    </style>
+</head>
+<body>
+
+<h1>Ajax Put 上传</h1>
+
+<input id="fileSelector" type="file">
+<input id="submitBtn" type="submit">
+
+<div id="msg"></div>
+
+<script src="common/cos-auth.min.js"></script>
+<script>
+    (function () {
+        // 请求用到的参数
+        var Bucket = 'test-1250000000';
+        var Region = 'ap-guangzhou';
+        var protocol = location.protocol === 'https:' ? 'https:' : 'http:';
+        var prefix = protocol + '//' + Bucket + '.cos.' + Region + '.myqcloud.com/';
+
+        // 对更多字符编码的 url encode 格式
+        var camSafeUrlEncode = function (str) {
+            return encodeURIComponent(str)
+                .replace(/!/g, '%21')
+                .replace(/'/g, '%27')
+                .replace(/\(/g, '%28')
+                .replace(/\)/g, '%29')
+                .replace(/\*/g, '%2A');
+        };
+
+        // 计算签名
+        var getAuthorization = function (options, callback) {
+            // var url = 'http://127.0.0.1:3000/sts-auth';
+            var url = '../server/sts.php';
+            var xhr = new XMLHttpRequest();
+            xhr.open('GET', url, true);
+            xhr.onload = function (e) {
+                var credentials;
+                try {
+                    credentials = (new Function('return ' + xhr.responseText))().credentials;
+                } catch (e) {}
+                if (credentials) {
+                    callback(null, {
+                        SecurityToken: credentials.sessionToken,
+                        Authorization: CosAuth({
+                            SecretId: credentials.tmpSecretId,
+                            SecretKey: credentials.tmpSecretKey,
+                            Method: options.Method,
+                            Pathname: options.Pathname,
+                        })
+                    });
+                } else {
+                    console.error(xhr.responseText);
+                    callback('获取签名出错');
+                }
+            };
+            xhr.onerror = function (e) {
+                callback('获取签名出错');
+            };
+            xhr.send();
+        };
+
+        // 上传文件
+        var uploadFile = function (file, callback) {
+            var Key = 'dir/' + file.name; // 这里指定上传目录和文件名
+            getAuthorization({Method: 'PUT', Pathname: '/' + Key}, function (err, info) {
+
+                if (err) {
+                    alert(err);
+                    return;
+                }
+
+                var auth = info.Authorization;
+                var SecurityToken = info.SecurityToken;
+                var url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, '/');
+                var xhr = new XMLHttpRequest();
+                xhr.open('PUT', url, true);
+                xhr.setRequestHeader('Authorization', auth);
+                SecurityToken && xhr.setRequestHeader('x-cos-security-token', SecurityToken);
+                xhr.upload.onprogress = function (e) {
+                    console.log('上传进度 ' + (Math.round(e.loaded / e.total * 10000) / 100) + '%');
+                };
+                xhr.onload = function () {
+                    if (xhr.status === 200 || xhr.status === 206) {
+                        var ETag = xhr.getResponseHeader('etag');
+                        callback(null, {url: url, ETag: ETag});
+                    } else {
+                        callback('文件 ' + Key + ' 上传失败,状态码:' + xhr.status);
+                    }
+                };
+                xhr.onerror = function () {
+                    callback('文件 ' + Key + ' 上传失败,请检查是否没配置 CORS 跨域规则');
+                };
+                xhr.send(file);
+            });
+        };
+
+        // 监听表单提交
+        document.getElementById('submitBtn').onclick = function (e) {
+            var file = document.getElementById('fileSelector').files[0];
+            if (!file) {
+                document.getElementById('msg').innerText = '未选择上传文件';
+                return;
+            }
+            file && uploadFile(file, function (err, data) {
+                console.log(err || data);
+                document.getElementById('msg').innerText = err ? err : ('上传成功,ETag=' + data.ETag);
+            });
+        };
+    })();
+</script>
+
+</body>
+</html>

Разница между файлами не показана из-за своего большого размера
+ 9804 - 0
node_modules/cos-js-sdk-v5/demo/vueDemo/cos-js-sdk-v5.js


+ 56 - 0
node_modules/cos-js-sdk-v5/demo/vueDemo/index.html

@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>COS-SDK-Vue-demo</title>
+  <script src="./vue.min.js"></script>
+  <!-- 使用时替换为当前最新版sdk -->
+  <script src="./cos-js-sdk-v5.js"></script>
+  <script src="index.js"></script>
+  <style>
+    table {width: 100%; border: solid 1px #ddd;}
+    table td {padding: 0 10px;}
+    .more-btn {display: block; margin: 10px auto 0;}
+  </style>
+</head>
+<body>
+  <div id="app">
+    <div class="nav">
+      <span v-for="(item, index) in navList" :key="index" style="margin-right: 5px;">
+        <a href="javascript:void(0)" @click="navClick(item)">{{item.name}}</a>
+        <span v-if="index !== navList.length - 1">/</span>
+      </span>
+    </div>
+    <div style="margin: 10px 0;">
+      <button @click="uploadFileClick" style="margin: 0 10px 0 0;">上传文件</button>
+      <button @click="uploadFolderClick">上传文件夹</button>
+      <input type="file" style="display: none;" @change="uploadChange" class="file-select">
+      <input type="file" style="display: none;" @change="uploadChange" class="folder-select" webkitdirectory multiple>
+    </div>
+    <div class="file-list">
+      <table border="1" cellpadding="0" cellspacing="0">
+        <thead>
+          <th v-for="(item, index) in columns" :key="index">{{item.label}}</th>
+        </thead>
+        <tbody>
+          <tr v-for="(item, index) in list" :key="index">
+            <td>
+              <a v-if="item.isDir" href="javascript:void(0)" @click="openFolder(item.Prefix)">{{item.name}}</a>
+              <span v-else>{{item.name}}</span>
+            </td>
+            <td>{{item.Size || '-'}}</td>
+            <td>{{item.LastModified || '-'}}</td>
+            <td>
+              <a v-if="!item.isDir" href="javascript:void(0)" @click="downloadFile(item)">下载</a>
+              <a v-if="!item.isDir" href="javascript:void(0)" @click="deleteFile(item)">删除</a>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <button v-if="hasMore === 'true'" class="more-btn" @click="loadMore">加载更多</button>
+    </div>
+  </div>
+</body>
+</html>

+ 185 - 0
node_modules/cos-js-sdk-v5/demo/vueDemo/index.js

@@ -0,0 +1,185 @@
+window.onload = function() {
+  const Bucket = 'examplebucket-1250000000';  /* 存储桶 */
+  const Region = 'ap-beijing';  /* 存储桶所在地域,必须字段 */
+  // SecretId 和 SecretKey请登录 https://console.cloud.tencent.com/cam/capi 进行查看和管理
+  const cos = new COS({
+    SecretId: '',
+    SecretKey: '',
+  });
+
+  /*
+    实现了以下功能
+    - 文件列表
+    - 上传文件
+    - 上传文件夹
+    - 下载文件
+    - 删除文件
+  */
+  const vm = new Vue({
+    el: '#app',
+    data() {
+      return {
+        columns: [
+          { label: '名称', value: 'Key' },
+          { label: '大小', value: 'Size' },
+          { label: '修改时间', value: 'LastModified' },
+          { label: '操作', value: 'action' }
+        ],
+        list: [],
+        Prefix: '',
+        Marker: '',
+        hasMore: false,
+      }
+    },
+    computed: {
+      // 面包屑导航条
+      navList() {
+        const prefixes = this.Prefix.split('/').filter(Boolean);
+        const folders = prefixes.map((item, index) => {
+          return {
+            name: item,
+            Prefix: prefixes.slice(0, index + 1).join('/') + '/',
+          };
+        });
+        return [{ name: Bucket, Prefix: ''}].concat(folders);
+      },
+    },
+    created() {
+      this.getFileList();
+    },
+    methods: {
+      // 查询文件列表
+      getFileList(loadMore) {
+        const { Prefix, Marker } = this;
+        cos.getBucket({
+          Bucket, /* 必须 */
+          Region,     /* 存储桶所在地域,必须字段 */
+          Prefix,              /* 非必须 */
+          Marker,       /* 非必须 */
+          Delimiter: '/',            /* 非必须 */
+       }, (err, data) => {
+          if(err) {
+            console.log(err);
+            return;
+          }
+          const folder = data.CommonPrefixes.map((item) => {
+            return {
+              Prefix: item.Prefix,
+              name: item.Prefix.replace(Prefix, '').slice(0,-1),
+              isDir: true,
+            }
+          });
+          const files = data.Contents.filter((item) => !item.Key.endsWith('/'))
+                        .map((item) => {
+                          return {
+                            ...item,
+                            name: item.Key.replace(Prefix, ''),
+                          }
+                        });
+          const list = folder.concat(files);
+          this.hasMore = data.IsTruncated;
+          this.Marker = data.NextMarker || '';
+          if (loadMore) {
+            this.list = [...this.list, ...list];
+          } else {
+            this.list = list;
+          }
+       });
+      },
+      // 点击面包屑
+      navClick(item) {
+        this.openFolder(item.Prefix);
+      },
+      // 打开文件夹
+      openFolder(prefix) {
+        this.Prefix = prefix;
+        this.hasMore = false;
+        this.Marker = '';
+        this.getFileList();
+      },
+      // 上传文件
+      uploadFileClick() {
+        document.querySelectorAll('.file-select')[0].click();
+      },
+      // 上传文件夹
+      uploadFolderClick() {
+        document.querySelectorAll('.folder-select')[0].click();
+      },
+      // 上传
+      uploadChange(events) {
+        const files = events.currentTarget.files;
+        const uploadFileList = [...files].map((file) => {
+          const path = file.webkitRelativePath || file.name;
+          return {
+            Bucket,
+            Region,
+            Key: this.Prefix + path,
+            Body: file,
+          }
+        });
+        cos.uploadFiles({
+          files: uploadFileList,
+          SliceSize: 1024 * 1024 * 10,    /* 设置大于10MB采用分块上传 */
+          onProgress: function (info) {
+              var percent = parseInt(info.percent * 10000) / 100;
+              var speed = parseInt(info.speed / 1024 / 1024 * 100) / 100;
+              console.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
+          },
+          onFileFinish: function (err, data, options) {
+              console.log(options.Key + '上传' + (err ? '失败' : '完成'));
+          },
+       }, (err, data) => {
+          if (err) {
+            console.log('上传失败', err);
+            return;
+          }
+          // 刷新列表前初始化
+          this.hasMore = false;
+          this.Marker = '';
+          this.getFileList();
+       });
+      },
+      // 加载更多
+      loadMore() {
+        this.getFileList(true);
+      },
+      // 下载
+      downloadFile(file) {
+        cos.getObjectUrl({
+          Bucket, /* 必须 */
+          Region,     /* 存储桶所在地域,必须字段 */
+          Key: file.Key,              /* 必须 */
+        }, function(err, data) {
+          if (err) {
+            console.log(err);
+            return;
+          }
+          const url = data.Url + (data.Url.indexOf('?') > -1 ? '&' : '?') + 'response-content-disposition=attachment'; // 补充强制下载的参数
+          // 使用iframe下载
+          const elemIF = document.createElement("iframe");
+          elemIF.src = url;
+          elemIF.style.display = "none";
+          document.body.appendChild(elemIF);
+        });
+      },
+      // 删除
+      deleteFile(file) {
+        cos.deleteObject({
+          Bucket, /* 必须 */
+          Region,     /* 存储桶所在地域,必须字段 */
+          Key: file.Key        /* 必须 */
+       }, (err, data) => {
+          if (err) {
+            console.log(err);
+            return;
+          }
+          // 刷新列表前初始化
+          this.hasMore = false;
+          this.Marker = '';
+          this.getFileList();
+       });
+      },
+    },
+  });
+}
+

Разница между файлами не показана из-за своего большого размера
+ 6 - 0
node_modules/cos-js-sdk-v5/demo/vueDemo/vue.min.js


Разница между файлами не показана из-за своего большого размера
+ 9943 - 0
node_modules/cos-js-sdk-v5/dist/cos-js-sdk-v5.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/cos-js-sdk-v5/dist/cos-js-sdk-v5.min.js


Разница между файлами не показана из-за своего большого размера
+ 2283 - 0
node_modules/cos-js-sdk-v5/index.d.ts


+ 2 - 0
node_modules/cos-js-sdk-v5/index.js

@@ -0,0 +1,2 @@
+var COS = require('./src/cos');
+module.exports = COS;

Разница между файлами не показана из-за своего большого размера
+ 128 - 0
node_modules/cos-js-sdk-v5/lib/crypto.js


+ 167 - 0
node_modules/cos-js-sdk-v5/lib/json2xml.js

@@ -0,0 +1,167 @@
+//copyright Ryan Day 2010 <http://ryanday.org>, Joscha Feth 2013 <http://www.feth.com> [MIT Licensed]
+
+var element_start_char =
+    "a-zA-Z_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FFF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD";
+var element_non_start_char = "\-.0-9\u00B7\u0300-\u036F\u203F\u2040";
+var element_replace = new RegExp("^([^" + element_start_char + "])|^((x|X)(m|M)(l|L))|([^" + element_start_char + element_non_start_char + "])", "g");
+var not_safe_in_xml = /[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]/gm;
+
+var objKeys = function (obj) {
+    var l = [];
+    if (obj instanceof Object) {
+        for (var k in obj) {
+            if (obj.hasOwnProperty(k)) {
+                l.push(k);
+            }
+        }
+    }
+    return l;
+};
+var process_to_xml = function (node_data, options) {
+
+    var makeNode = function (name, content, attributes, level, hasSubNodes) {
+        var indent_value = options.indent !== undefined ? options.indent : "\t";
+        var indent = options.prettyPrint ? '\n' + new Array(level).join(indent_value) : '';
+        if (options.removeIllegalNameCharacters) {
+            name = name.replace(element_replace, '_');
+        }
+
+        var node = [indent, '<', name, (attributes || '')];
+        if (content && content.length > 0) {
+            node.push('>')
+            node.push(content);
+            hasSubNodes && node.push(indent);
+            node.push('</');
+            node.push(name);
+            node.push('>');
+        } else {
+            node.push('/>');
+        }
+        return node.join('');
+    };
+
+    return (function fn(node_data, node_descriptor, level) {
+        var type = typeof node_data;
+        if ((Array.isArray) ? Array.isArray(node_data) : node_data instanceof Array) {
+            type = 'array';
+        } else if (node_data instanceof Date) {
+            type = 'date';
+        }
+
+        switch (type) {
+            //if value is an array create child nodes from values
+            case 'array':
+                var ret = [];
+                node_data.map(function (v) {
+                    ret.push(fn(v, 1, level + 1));
+                    //entries that are values of an array are the only ones that can be special node descriptors
+                });
+                options.prettyPrint && ret.push('\n');
+                return ret.join('');
+                break;
+
+            case 'date':
+                // cast dates to ISO 8601 date (soap likes it)
+                return node_data.toJSON ? node_data.toJSON() : node_data + '';
+                break;
+
+            case 'object':
+                var nodes = [];
+                for (var name in node_data) {
+                    if (node_data.hasOwnProperty(name)) {
+                        if (node_data[name] instanceof Array) {
+                            for (var j = 0; j < node_data[name].length; j++) {
+                                if (node_data[name].hasOwnProperty(j)) {
+                                    nodes.push(makeNode(name, fn(node_data[name][j], 0, level + 1), null, level + 1, objKeys(node_data[name][j]).length));
+                                }
+                            }
+                        } else {
+                            nodes.push(makeNode(name, fn(node_data[name], 0, level + 1), null, level + 1));
+                        }
+                    }
+                }
+                options.prettyPrint && nodes.length > 0 && nodes.push('\n');
+                return nodes.join('');
+                break;
+
+            case 'function':
+                return node_data();
+                break;
+
+            default:
+                return options.escape ? esc(node_data) : '' + node_data;
+        }
+
+    }(node_data, 0, 0))
+};
+
+
+var xml_header = function (standalone) {
+    var ret = ['<?xml version="1.0" encoding="UTF-8"'];
+
+    if (standalone) {
+        ret.push(' standalone="yes"');
+    }
+    ret.push('?>');
+
+    return ret.join('');
+};
+
+function esc(str) {
+    return ('' + str).replace(/&/g, '&amp;')
+        .replace(/</g, '&lt;')
+        .replace(/>/g, '&gt;')
+        .replace(/'/g, '&apos;')
+        .replace(/"/g, '&quot;')
+        .replace(not_safe_in_xml, '');
+}
+
+module.exports = function (obj, options) {
+    if (!options) {
+        options = {
+            xmlHeader: {
+                standalone: true
+            },
+            prettyPrint: true,
+            indent: "  ",
+            escape: true,
+        };
+    }
+
+    if (typeof obj == 'string') {
+        try {
+            obj = JSON.parse(obj.toString());
+        } catch (e) {
+            return false;
+        }
+    }
+
+    var xmlheader = '';
+    var docType = '';
+    if (options) {
+        if (typeof options == 'object') {
+            // our config is an object
+
+            if (options.xmlHeader) {
+                // the user wants an xml header
+                xmlheader = xml_header(!!options.xmlHeader.standalone);
+            }
+
+            if (typeof options.docType != 'undefined') {
+                docType = '<!DOCTYPE ' + options.docType + '>'
+            }
+        } else {
+            // our config is a boolean value, so just add xml header
+            xmlheader = xml_header();
+        }
+    }
+    options = options || {}
+
+    var ret = [
+        xmlheader,
+        (options.prettyPrint && docType ? '\n' : ''),
+        docType,
+        process_to_xml(obj, options)
+    ];
+    return ret.join('').replace(/\n{2,}/g, '\n').replace(/\s+$/g, '');
+};

+ 648 - 0
node_modules/cos-js-sdk-v5/lib/md5.js

@@ -0,0 +1,648 @@
+/* https://github.com/emn178/js-md5 */
+(function () {
+    'use strict';
+
+    var ERROR = 'input is invalid type';
+    var WINDOW = typeof window === 'object';
+    var root = WINDOW ? window : {};
+    if (root.JS_MD5_NO_WINDOW) {
+        WINDOW = false;
+    }
+    var WEB_WORKER = !WINDOW && typeof self === 'object';
+    var NODE_JS = !root.JS_MD5_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
+    if (NODE_JS) {
+        root = global;
+    } else if (WEB_WORKER) {
+        root = self;
+    }
+    var COMMON_JS = !root.JS_MD5_NO_COMMON_JS && typeof module === 'object' && module.exports;
+    var AMD = typeof define === 'function' && define.amd;
+    var ARRAY_BUFFER = !root.JS_MD5_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
+    var HEX_CHARS = '0123456789abcdef'.split('');
+    var EXTRA = [128, 32768, 8388608, -2147483648];
+    var SHIFT = [0, 8, 16, 24];
+    var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64'];
+    var BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
+
+    var blocks = [], buffer8;
+    if (ARRAY_BUFFER) {
+        var buffer = new ArrayBuffer(68);
+        buffer8 = new Uint8Array(buffer);
+        blocks = new Uint32Array(buffer);
+    }
+
+    if (root.JS_MD5_NO_NODE_JS || !Array.isArray) {
+        Array.isArray = function (obj) {
+            return Object.prototype.toString.call(obj) === '[object Array]';
+        };
+    }
+
+    if (ARRAY_BUFFER && (root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
+        ArrayBuffer.isView = function (obj) {
+            return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
+        };
+    }
+
+    /**
+     * @method hex
+     * @memberof md5
+     * @description Output hash as hex string
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {String} Hex string
+     * @example
+     * md5.hex('The quick brown fox jumps over the lazy dog');
+     * // equal to
+     * md5('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method digest
+     * @memberof md5
+     * @description Output hash as bytes array
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Array} Bytes array
+     * @example
+     * md5.digest('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method array
+     * @memberof md5
+     * @description Output hash as bytes array
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Array} Bytes array
+     * @example
+     * md5.array('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method arrayBuffer
+     * @memberof md5
+     * @description Output hash as ArrayBuffer
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @example
+     * md5.arrayBuffer('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method buffer
+     * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
+     * @memberof md5
+     * @description Output hash as ArrayBuffer
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @example
+     * md5.buffer('The quick brown fox jumps over the lazy dog');
+     */
+    /**
+     * @method base64
+     * @memberof md5
+     * @description Output hash as base64 string
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {String} base64 string
+     * @example
+     * md5.base64('The quick brown fox jumps over the lazy dog');
+     */
+    var createOutputMethod = function (outputType) {
+        return function (message, isBinStr) {
+            return new Md5(true).update(message, isBinStr)[outputType]();
+        };
+    };
+
+    /**
+     * @method create
+     * @memberof md5
+     * @description Create Md5 object
+     * @returns {Md5} Md5 object.
+     * @example
+     * var hash = md5.create();
+     */
+    /**
+     * @method update
+     * @memberof md5
+     * @description Create and update Md5 object
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Md5} Md5 object.
+     * @example
+     * var hash = md5.update('The quick brown fox jumps over the lazy dog');
+     * // equal to
+     * var hash = md5.create();
+     * hash.update('The quick brown fox jumps over the lazy dog');
+     */
+    var createMethod = function () {
+        var method = createOutputMethod('hex');
+        if (NODE_JS) {
+            method = nodeWrap(method);
+        }
+        method.getCtx = method.create = function () {
+            return new Md5();
+        };
+        method.update = function (message) {
+            return method.create().update(message);
+        };
+        for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
+            var type = OUTPUT_TYPES[i];
+            method[type] = createOutputMethod(type);
+        }
+        return method;
+    };
+
+    var nodeWrap = function (method) {
+        var crypto = eval("require('crypto')");
+        var Buffer = eval("require('buffer').Buffer");
+        var nodeMethod = function (message) {
+            if (typeof message === 'string') {
+                return crypto.createHash('md5').update(message, 'utf8').digest('hex');
+            } else {
+                if (message === null || message === undefined) {
+                    throw ERROR;
+                } else if (message.constructor === ArrayBuffer) {
+                    message = new Uint8Array(message);
+                }
+            }
+            if (Array.isArray(message) || ArrayBuffer.isView(message) ||
+                message.constructor === Buffer) {
+                return crypto.createHash('md5').update(new Buffer(message)).digest('hex');
+            } else {
+                return method(message);
+            }
+        };
+        return nodeMethod;
+    };
+
+    /**
+     * Md5 class
+     * @class Md5
+     * @description This is internal class.
+     * @see {@link md5.create}
+     */
+    function Md5(sharedMemory) {
+        if (sharedMemory) {
+            blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+                blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+                    blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+                        blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+            this.blocks = blocks;
+            this.buffer8 = buffer8;
+        } else {
+            if (ARRAY_BUFFER) {
+                var buffer = new ArrayBuffer(68);
+                this.buffer8 = new Uint8Array(buffer);
+                this.blocks = new Uint32Array(buffer);
+            } else {
+                this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+            }
+        }
+        this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0;
+        this.finalized = this.hashed = false;
+        this.first = true;
+    }
+
+    /**
+     * @method update
+     * @memberof Md5
+     * @instance
+     * @description Update hash
+     * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+     * @returns {Md5} Md5 object.
+     * @see {@link md5.update}
+     */
+    Md5.prototype.update = function (message, isBinStr) {
+        if (this.finalized) {
+            return;
+        }
+
+        var code, index = 0, i, length = message.length, blocks = this.blocks;
+        var buffer8 = this.buffer8;
+
+        while (index < length) {
+            if (this.hashed) {
+                this.hashed = false;
+                blocks[0] = blocks[16];
+                blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+                    blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+                        blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+                            blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+            }
+
+            if (ARRAY_BUFFER) {
+                for (i = this.start; index < length && i < 64; ++index) {
+                    code = message.charCodeAt(index);
+                    if (isBinStr || code < 0x80) {
+                        buffer8[i++] = code;
+                    } else if (code < 0x800) {
+                        buffer8[i++] = 0xc0 | (code >> 6);
+                        buffer8[i++] = 0x80 | (code & 0x3f);
+                    } else if (code < 0xd800 || code >= 0xe000) {
+                        buffer8[i++] = 0xe0 | (code >> 12);
+                        buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
+                        buffer8[i++] = 0x80 | (code & 0x3f);
+                    } else {
+                        code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
+                        buffer8[i++] = 0xf0 | (code >> 18);
+                        buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);
+                        buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
+                        buffer8[i++] = 0x80 | (code & 0x3f);
+                    }
+                }
+            } else {
+                for (i = this.start; index < length && i < 64; ++index) {
+                    code = message.charCodeAt(index);
+                    if (isBinStr || code < 0x80) {
+                        blocks[i >> 2] |= code << SHIFT[i++ & 3];
+                    } else if (code < 0x800) {
+                        blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
+                        blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+                    } else if (code < 0xd800 || code >= 0xe000) {
+                        blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
+                        blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
+                        blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+                    } else {
+                        code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
+                        blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
+                        blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
+                        blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
+                        blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
+                    }
+                }
+            }
+            this.lastByteIndex = i;
+            this.bytes += i - this.start;
+            if (i >= 64) {
+                this.start = i - 64;
+                this.hash();
+                this.hashed = true;
+            } else {
+                this.start = i;
+            }
+        }
+        if (this.bytes > 4294967295) {
+            this.hBytes += this.bytes / 4294967296 << 0;
+            this.bytes = this.bytes % 4294967296;
+        }
+        return this;
+    };
+
+    Md5.prototype.finalize = function () {
+        if (this.finalized) {
+            return;
+        }
+        this.finalized = true;
+        var blocks = this.blocks, i = this.lastByteIndex;
+        blocks[i >> 2] |= EXTRA[i & 3];
+        if (i >= 56) {
+            if (!this.hashed) {
+                this.hash();
+            }
+            blocks[0] = blocks[16];
+            blocks[16] = blocks[1] = blocks[2] = blocks[3] =
+                blocks[4] = blocks[5] = blocks[6] = blocks[7] =
+                    blocks[8] = blocks[9] = blocks[10] = blocks[11] =
+                        blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
+        }
+        blocks[14] = this.bytes << 3;
+        blocks[15] = this.hBytes << 3 | this.bytes >>> 29;
+        this.hash();
+    };
+
+    Md5.prototype.hash = function () {
+        var a, b, c, d, bc, da, blocks = this.blocks;
+
+        if (this.first) {
+            a = blocks[0] - 680876937;
+            a = (a << 7 | a >>> 25) - 271733879 << 0;
+            d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708;
+            d = (d << 12 | d >>> 20) + a << 0;
+            c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;
+            c = (c << 17 | c >>> 15) + d << 0;
+            b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;
+            b = (b << 22 | b >>> 10) + c << 0;
+        } else {
+            a = this.h0;
+            b = this.h1;
+            c = this.h2;
+            d = this.h3;
+            a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;
+            a = (a << 7 | a >>> 25) + b << 0;
+            d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;
+            d = (d << 12 | d >>> 20) + a << 0;
+            c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;
+            c = (c << 17 | c >>> 15) + d << 0;
+            b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;
+            b = (b << 22 | b >>> 10) + c << 0;
+        }
+
+        a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;
+        a = (a << 7 | a >>> 25) + b << 0;
+        d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;
+        d = (d << 12 | d >>> 20) + a << 0;
+        c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;
+        c = (c << 17 | c >>> 15) + d << 0;
+        b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;
+        b = (b << 22 | b >>> 10) + c << 0;
+        a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;
+        a = (a << 7 | a >>> 25) + b << 0;
+        d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;
+        d = (d << 12 | d >>> 20) + a << 0;
+        c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;
+        c = (c << 17 | c >>> 15) + d << 0;
+        b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;
+        b = (b << 22 | b >>> 10) + c << 0;
+        a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;
+        a = (a << 7 | a >>> 25) + b << 0;
+        d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;
+        d = (d << 12 | d >>> 20) + a << 0;
+        c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;
+        c = (c << 17 | c >>> 15) + d << 0;
+        b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;
+        b = (b << 22 | b >>> 10) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;
+        b = (b << 20 | b >>> 12) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;
+        b = (b << 20 | b >>> 12) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;
+        b = (b << 20 | b >>> 12) + c << 0;
+        a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;
+        a = (a << 5 | a >>> 27) + b << 0;
+        d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;
+        d = (d << 9 | d >>> 23) + a << 0;
+        c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;
+        c = (c << 14 | c >>> 18) + d << 0;
+        b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;
+        b = (b << 20 | b >>> 12) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[5] - 378558;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[8] - 2022574463;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[11] + 1839030562;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[14] - 35309556;
+        b = (b << 23 | b >>> 9) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[1] - 1530992060;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[4] + 1272893353;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[7] - 155497632;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[10] - 1094730640;
+        b = (b << 23 | b >>> 9) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[13] + 681279174;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[0] - 358537222;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[3] - 722521979;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[6] + 76029189;
+        b = (b << 23 | b >>> 9) + c << 0;
+        bc = b ^ c;
+        a += (bc ^ d) + blocks[9] - 640364487;
+        a = (a << 4 | a >>> 28) + b << 0;
+        d += (bc ^ a) + blocks[12] - 421815835;
+        d = (d << 11 | d >>> 21) + a << 0;
+        da = d ^ a;
+        c += (da ^ b) + blocks[15] + 530742520;
+        c = (c << 16 | c >>> 16) + d << 0;
+        b += (da ^ c) + blocks[2] - 995338651;
+        b = (b << 23 | b >>> 9) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[0] - 198630844;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[7] + 1126891415;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[14] - 1416354905;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[5] - 57434055;
+        b = (b << 21 | b >>> 11) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[12] + 1700485571;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[3] - 1894986606;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[10] - 1051523;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[1] - 2054922799;
+        b = (b << 21 | b >>> 11) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[8] + 1873313359;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[15] - 30611744;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[6] - 1560198380;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[13] + 1309151649;
+        b = (b << 21 | b >>> 11) + c << 0;
+        a += (c ^ (b | ~d)) + blocks[4] - 145523070;
+        a = (a << 6 | a >>> 26) + b << 0;
+        d += (b ^ (a | ~c)) + blocks[11] - 1120210379;
+        d = (d << 10 | d >>> 22) + a << 0;
+        c += (a ^ (d | ~b)) + blocks[2] + 718787259;
+        c = (c << 15 | c >>> 17) + d << 0;
+        b += (d ^ (c | ~a)) + blocks[9] - 343485551;
+        b = (b << 21 | b >>> 11) + c << 0;
+
+        if (this.first) {
+            this.h0 = a + 1732584193 << 0;
+            this.h1 = b - 271733879 << 0;
+            this.h2 = c - 1732584194 << 0;
+            this.h3 = d + 271733878 << 0;
+            this.first = false;
+        } else {
+            this.h0 = this.h0 + a << 0;
+            this.h1 = this.h1 + b << 0;
+            this.h2 = this.h2 + c << 0;
+            this.h3 = this.h3 + d << 0;
+        }
+    };
+
+    /**
+     * @method hex
+     * @memberof Md5
+     * @instance
+     * @description Output hash as hex string
+     * @returns {String} Hex string
+     * @see {@link md5.hex}
+     * @example
+     * hash.hex();
+     */
+    Md5.prototype.hex = function () {
+        this.finalize();
+
+        var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
+
+        return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
+            HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
+            HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
+            HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
+            HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
+            HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
+            HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
+            HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
+            HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
+            HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
+            HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
+            HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
+            HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
+            HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
+            HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
+            HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];
+    };
+
+    /**
+     * @method toString
+     * @memberof Md5
+     * @instance
+     * @description Output hash as hex string
+     * @returns {String} Hex string
+     * @see {@link md5.hex}
+     * @example
+     * hash.toString();
+     */
+    Md5.prototype.toString = Md5.prototype.hex;
+
+    /**
+     * @method digest
+     * @memberof Md5
+     * @instance
+     * @description Output hash as bytes array
+     * @returns {Array} Bytes array
+     * @see {@link md5.digest}
+     * @example
+     * hash.digest();
+     */
+    Md5.prototype.digest = function (format) {
+        if (format === 'hex') return this.hex();
+        this.finalize();
+
+        var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
+        var res = [
+            h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,
+            h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,
+            h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,
+            h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF
+        ];
+        return res;
+    };
+
+    /**
+     * @method array
+     * @memberof Md5
+     * @instance
+     * @description Output hash as bytes array
+     * @returns {Array} Bytes array
+     * @see {@link md5.array}
+     * @example
+     * hash.array();
+     */
+    Md5.prototype.array = Md5.prototype.digest;
+
+    /**
+     * @method arrayBuffer
+     * @memberof Md5
+     * @instance
+     * @description Output hash as ArrayBuffer
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @see {@link md5.arrayBuffer}
+     * @example
+     * hash.arrayBuffer();
+     */
+    Md5.prototype.arrayBuffer = function () {
+        this.finalize();
+
+        var buffer = new ArrayBuffer(16);
+        var blocks = new Uint32Array(buffer);
+        blocks[0] = this.h0;
+        blocks[1] = this.h1;
+        blocks[2] = this.h2;
+        blocks[3] = this.h3;
+        return buffer;
+    };
+
+    /**
+     * @method buffer
+     * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
+     * @memberof Md5
+     * @instance
+     * @description Output hash as ArrayBuffer
+     * @returns {ArrayBuffer} ArrayBuffer
+     * @see {@link md5.buffer}
+     * @example
+     * hash.buffer();
+     */
+    Md5.prototype.buffer = Md5.prototype.arrayBuffer;
+
+    /**
+     * @method base64
+     * @memberof Md5
+     * @instance
+     * @description Output hash as base64 string
+     * @returns {String} base64 string
+     * @see {@link md5.base64}
+     * @example
+     * hash.base64();
+     */
+    Md5.prototype.base64 = function () {
+        var v1, v2, v3, base64Str = '', bytes = this.array();
+        for (var i = 0; i < 15;) {
+            v1 = bytes[i++];
+            v2 = bytes[i++];
+            v3 = bytes[i++];
+            base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
+                BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] +
+                BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] +
+                BASE64_ENCODE_CHAR[v3 & 63];
+        }
+        v1 = bytes[i];
+        base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
+            BASE64_ENCODE_CHAR[(v1 << 4) & 63] +
+            '==';
+        return base64Str;
+    };
+
+    var exports = createMethod();
+
+    if (COMMON_JS) {
+        module.exports = exports;
+    } else {
+        /**
+         * @method md5
+         * @description Md5 hash function, export to global in browsers.
+         * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
+         * @returns {String} md5 hashes
+         * @example
+         * md5(''); // d41d8cd98f00b204e9800998ecf8427e
+         * md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6
+         * md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0
+         *
+         * // It also supports UTF-8 encoding
+         * md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07
+         *
+         * // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`
+         * md5([]); // d41d8cd98f00b204e9800998ecf8427e
+         * md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e
+         */
+        root.md5 = exports;
+        if (AMD) {
+            define(function () {
+                return exports;
+            });
+        }
+    }
+})();

+ 136 - 0
node_modules/cos-js-sdk-v5/lib/request.js

@@ -0,0 +1,136 @@
+var stringifyPrimitive = function(v) {
+    switch (typeof v) {
+        case 'string':
+            return v;
+        case 'boolean':
+            return v ? 'true' : 'false';
+        case 'number':
+            return isFinite(v) ? v : '';
+        default:
+            return '';
+    }
+};
+
+var queryStringify = function(obj, sep, eq, name) {
+    sep = sep || '&';
+    eq = eq || '=';
+    if (obj === null) {
+        obj = undefined;
+    }
+    if (typeof obj === 'object') {
+        return Object.keys(obj).map(function(k) {
+            var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
+            if (Array.isArray(obj[k])) {
+                return obj[k].map(function(v) {
+                    return ks + encodeURIComponent(stringifyPrimitive(v));
+                }).join(sep);
+            } else {
+                return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
+            }
+        }).filter(Boolean).join(sep);
+
+    }
+    if (!name) return '';
+    return encodeURIComponent(stringifyPrimitive(name)) + eq +
+        encodeURIComponent(stringifyPrimitive(obj));
+};
+
+var xhrRes = function (err, xhr, body) {
+    var headers = {};
+    xhr.getAllResponseHeaders().trim().split('\n').forEach(function (item) {
+        if (item) {
+            var index = item.indexOf(':');
+            var key = item.substr(0, index).trim().toLowerCase();
+            var val = item.substr(index + 1).trim();
+            headers[key] = val;
+        }
+    });
+    return {
+        error: err,
+        statusCode: xhr.status,
+        statusMessage: xhr.statusText,
+        headers: headers,
+        body: body,
+    };
+};
+
+var xhrBody = function (xhr, dataType) {
+    return !dataType && dataType === 'text' ? xhr.responseText : xhr.response;
+};
+
+var request = function (opt, callback) {
+
+    // method
+    var method = (opt.method || 'GET').toUpperCase();
+
+    // url、qs
+    var url = opt.url;
+    if (opt.qs) {
+        var qsStr = queryStringify(opt.qs);
+        if (qsStr) {
+            url += (url.indexOf('?') === -1 ? '?' : '&') + qsStr;
+        }
+    }
+
+    // 创建 ajax 实例
+    var xhr = new XMLHttpRequest();
+    xhr.open(method, url, true);
+    xhr.responseType = opt.dataType || 'text';
+
+    // 处理 xhrFields 属性
+    if (opt.xhrFields) {
+        for (var xhrField in opt.xhrFields) {
+            xhr[xhrField] = opt.xhrFields[xhrField]
+        }
+    }
+
+    // 处理 headers
+    var headers = opt.headers;
+    if (headers) {
+        for (var key in headers) {
+            if (headers.hasOwnProperty(key) &&
+                key.toLowerCase() !== 'content-length' &&
+                key.toLowerCase() !== 'user-agent' &&
+                key.toLowerCase() !== 'origin' &&
+                key.toLowerCase() !== 'host') {
+                xhr.setRequestHeader(key, headers[key]);
+            }
+        }
+    }
+
+    // onprogress
+    if (opt.onProgress && xhr.upload) xhr.upload.onprogress = opt.onProgress;
+    if (opt.onDownloadProgress) xhr.onprogress = opt.onDownloadProgress;
+
+    // timeout
+    if (opt.timeout) xhr.timeout = opt.timeout;
+    xhr.ontimeout = function(event){
+        var error = new Error('timeout');
+        callback(xhrRes(error, xhr));
+    };
+
+    // success 2xx/3xx/4xx
+    xhr.onload = function () {
+        callback(xhrRes(null, xhr, xhrBody(xhr, opt.dataType)));
+    };
+
+    // error 5xx/0 (网络错误、跨域报错、Https connect-src 限制的报错时 statusCode 为 0)
+    xhr.onerror = function (err) {
+        var body = xhrBody(xhr, opt.dataType);
+        if (body) { // 5xx
+            callback(xhrRes(null, xhr, body));
+        } else { // 0
+            var error = xhr.statusText;
+            if (!error && xhr.status === 0) error = new Error('CORS blocked or network error');
+            callback(xhrRes(error, xhr, body));
+        }
+    };
+
+    // send
+    xhr.send(opt.body || '');
+
+    // 返回 ajax 实例,用于外部调用 xhr.abort
+    return xhr;
+};
+
+module.exports = request;

+ 166 - 0
node_modules/cos-js-sdk-v5/lib/xml2json.js

@@ -0,0 +1,166 @@
+/* Copyright 2015 William Summers, MetaTribal LLC
+ * adapted from https://developer.mozilla.org/en-US/docs/JXON
+ *
+ * Licensed under the MIT License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/MIT
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author William Summers
+ * https://github.com/metatribal/xmlToJSON
+ */
+var DOMParser = require('xmldom').DOMParser;
+
+var xmlToJSON = (function () {
+
+    this.version = "1.3.5";
+
+    var options = { // set up the default options
+        mergeCDATA: true, // extract cdata and merge with text
+        normalize: true, // collapse multiple spaces to single space
+        stripElemPrefix: true, // for elements of same name in diff namespaces, you can enable namespaces and access the nskey property
+    };
+
+    var prefixMatch = new RegExp(/(?!xmlns)^.*:/);
+    var trimMatch = new RegExp(/^\s+|\s+$/g);
+
+    this.grokType = function (sValue) {
+        if (/^\s*$/.test(sValue)) {
+            return null;
+        }
+        if (/^(?:true|false)$/i.test(sValue)) {
+            return sValue.toLowerCase() === "true";
+        }
+        if (isFinite(sValue)) {
+            return parseFloat(sValue);
+        }
+        return sValue;
+    };
+
+    this.parseString = function (xmlString, opt) {
+        if (xmlString) {
+            var xml = this.stringToXML(xmlString);
+            if (xml.getElementsByTagName('parsererror').length) {
+                return null;
+            } else {
+                return this.parseXML(xml, opt);
+            }
+        } else {
+            return null;
+        }
+    };
+
+    this.parseXML = function (oXMLParent, opt) {
+
+        // initialize options
+        for (var key in opt) {
+            options[key] = opt[key];
+        }
+
+        var vResult = {},
+            nLength = 0,
+            sCollectedTxt = "";
+
+        // iterate over the children
+        var childNum = oXMLParent.childNodes.length;
+        if (childNum) {
+            for (var oNode, sProp, vContent, nItem = 0; nItem < oXMLParent.childNodes.length; nItem++) {
+                oNode = oXMLParent.childNodes.item(nItem);
+
+                if (oNode.nodeType === 4) {
+                    if (options.mergeCDATA) {
+                        sCollectedTxt += oNode.nodeValue;
+                    }
+                } /* nodeType is "CDATASection" (4) */
+                else if (oNode.nodeType === 3) {
+                    sCollectedTxt += oNode.nodeValue;
+                } /* nodeType is "Text" (3) */
+                else if (oNode.nodeType === 1) { /* nodeType is "Element" (1) */
+
+                    if (nLength === 0) {
+                        vResult = {};
+                    }
+
+                    // using nodeName to support browser (IE) implementation with no 'localName' property
+                    if (options.stripElemPrefix) {
+                        sProp = oNode.nodeName.replace(prefixMatch, '');
+                    } else {
+                        sProp = oNode.nodeName;
+                    }
+
+                    vContent = xmlToJSON.parseXML(oNode);
+
+                    if (vResult.hasOwnProperty(sProp)) {
+                        if (vResult[sProp].constructor !== Array) {
+                            vResult[sProp] = [vResult[sProp]];
+                        }
+                        vResult[sProp].push(vContent);
+
+                    } else {
+                        vResult[sProp] = vContent;
+                        nLength++;
+                    }
+                }
+            }
+        }
+
+        if (!Object.keys(vResult).length) {
+            // vResult = sCollectedTxt.replace(trimMatch, '') || ''; // by carsonxu 修复 getBucket返回的 Key 是 " /" 这种场景
+            vResult = sCollectedTxt || '';
+        }
+
+        return vResult;
+    };
+
+    // Convert xmlDocument to a string
+    // Returns null on failure
+    this.xmlToString = function (xmlDoc) {
+        try {
+            var xmlString = xmlDoc.xml ? xmlDoc.xml : (new XMLSerializer()).serializeToString(xmlDoc);
+            return xmlString;
+        } catch (err) {
+            return null;
+        }
+    };
+
+    // Convert a string to XML Node Structure
+    // Returns null on failure
+    this.stringToXML = function (xmlString) {
+        try {
+            var xmlDoc = null;
+
+            if (window.DOMParser) {
+
+                var parser = new DOMParser();
+                xmlDoc = parser.parseFromString(xmlString, "text/xml");
+
+                return xmlDoc;
+            } else {
+                xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+                xmlDoc.async = false;
+                xmlDoc.loadXML(xmlString);
+
+                return xmlDoc;
+            }
+        } catch (e) {
+            return null;
+        }
+    };
+
+    return this;
+
+}).call({});
+
+var xml2json = function (xmlString) {
+    return xmlToJSON.parseString(xmlString);
+};
+
+module.exports = xml2json;

+ 70 - 0
node_modules/cos-js-sdk-v5/package.json

@@ -0,0 +1,70 @@
+{
+  "_from": "cos-js-sdk-v5",
+  "_id": "cos-js-sdk-v5@1.3.1",
+  "_inBundle": false,
+  "_integrity": "sha512-Q12rZXb6eHeyMwloblVMYha4VlGd4+4iJkXLL2YUxPEc3c9GNZeso88ujBUKrxu3wF+Z6vbth/DJ3fQkpPTi+Q==",
+  "_location": "/cos-js-sdk-v5",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "tag",
+    "registry": true,
+    "raw": "cos-js-sdk-v5",
+    "name": "cos-js-sdk-v5",
+    "escapedName": "cos-js-sdk-v5",
+    "rawSpec": "",
+    "saveSpec": null,
+    "fetchSpec": "latest"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://repo.huaweicloud.com/repository/npm/cos-js-sdk-v5/-/cos-js-sdk-v5-1.3.1.tgz",
+  "_shasum": "f87e9c41201e32a82fd478ca1231ca6bb7485821",
+  "_spec": "cos-js-sdk-v5",
+  "_where": "H:\\company-project\\instant_messaging",
+  "author": {
+    "name": "carsonxu"
+  },
+  "bugs": {
+    "url": "https://github.com/tencentyun/cos-js-sdk-v5/issues"
+  },
+  "bundleDependencies": false,
+  "dependencies": {
+    "xmldom": "^0.1.31"
+  },
+  "deprecated": false,
+  "description": "JavaScript SDK for [腾讯云对象存储](https://cloud.tencent.com/product/cos)",
+  "devDependencies": {
+    "babel-core": "^6.26.0",
+    "babel-loader": "^7.1.2",
+    "body-parser": "^1.18.3",
+    "cos-nodejs-sdk-v5": "^2.10.0",
+    "cross-env": "^5.2.0",
+    "express": "^4.16.4",
+    "nyc": "^15.1.0",
+    "puppeteer": "^5.3.1",
+    "puppeteer-to-istanbul": "^1.4.0",
+    "qcloud-cos-sts": "^3.0.2",
+    "request": "^2.87.0",
+    "webpack": "^3.12.0"
+  },
+  "homepage": "https://github.com/tencentyun/cos-js-sdk-v5#readme",
+  "keywords": [],
+  "license": "ISC",
+  "main": "index.js",
+  "name": "cos-js-sdk-v5",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/tencentyun/cos-js-sdk-v5.git"
+  },
+  "scripts": {
+    "build": "cross-env NODE_ENV=production webpack",
+    "cos-auth.min.js": "uglifyjs ./demo/common/cos-auth.js -o ./demo/common/cos-auth.min.js -c -m",
+    "dev": "cross-env NODE_ENV=development webpack -w",
+    "nyc": "node test/watcher.js && nyc report --reporter=clover --reporter=cobertura",
+    "server": "node server/sts.js"
+  },
+  "types": "index.d.ts",
+  "version": "1.3.1"
+}

+ 171 - 0
node_modules/cos-js-sdk-v5/server/qcloud-sts-sdk.php

@@ -0,0 +1,171 @@
+<?php
+
+/**
+ * 代码出处:
+ * https://github.com/tencentyun/qcloud-cos-sts-sdk
+ */
+
+class STS{
+    // 临时密钥计算样例
+
+    function _hex2bin($data) {
+        $len = strlen($data);
+        return pack("H" . $len, $data);
+    }
+    // obj 转 query string
+    function json2str($obj, $notEncode = false) {
+        ksort($obj);
+        $arr = array();
+        if(!is_array($obj)){
+            throw new Exception($obj + " must be a array");
+        }
+        foreach ($obj as $key => $val) {
+            array_push($arr, $key . '=' . ($notEncode ? $val : rawurlencode($val)));
+        }
+        return join('&', $arr);
+    }
+    // 计算临时密钥用的签名
+    function getSignature($opt, $key, $method, $config) {
+        $formatString = $method . $config['domain'] . '/?' . $this->json2str($opt, 1);
+        $sign = hash_hmac('sha1', $formatString, $key);
+        $sign = base64_encode($this->_hex2bin($sign));
+        return $sign;
+    }
+    // v2接口的key首字母小写,v3改成大写,此处做了向下兼容
+    function backwardCompat($result) {
+        if(!is_array($result)){
+            throw new Exception($result + " must be a array");
+        }
+        $compat = array();
+        foreach ($result as $key => $value) {
+            if(is_array($value)) {
+                $compat[lcfirst($key)] = $this->backwardCompat($value);
+            } elseif ($key == 'Token') {
+                $compat['sessionToken'] = $value;
+            } else {
+                $compat[lcfirst($key)] = $value;
+            }
+        }
+        return $compat;
+    }
+    // 获取临时密钥
+    function getTempKeys($config) {
+        if(array_key_exists('bucket', $config)){
+            $ShortBucketName = substr($config['bucket'],0, strripos($config['bucket'], '-'));
+            $AppId = substr($config['bucket'], 1 + strripos($config['bucket'], '-'));
+        }
+        if(array_key_exists('policy', $config)){
+            $policy = $config['policy'];
+        }else{
+            $policy = array(
+                'version'=> '2.0',
+                'statement'=> array(
+                    array(
+                        'action'=> $config['allowActions'],
+                        'effect'=> 'allow',
+                        'principal'=> array('qcs'=> array('*')),
+                        'resource'=> array(
+                            'qcs::cos:' . $config['region'] . ':uid/' . $AppId . ':prefix//' . $AppId . '/' . $ShortBucketName . '/' . $config['allowPrefix']
+                        )
+                    )
+                )
+            );
+        }
+        $policyStr = str_replace('\\/', '/', json_encode($policy));
+        $Action = 'GetFederationToken';
+        $Nonce = rand(10000, 20000);
+        $Timestamp = time();
+        $Method = 'POST';
+        $params = array(
+            'SecretId'=> $config['secretId'],
+            'Timestamp'=> $Timestamp,
+            'Nonce'=> $Nonce,
+            'Action'=> $Action,
+            'DurationSeconds'=> $config['durationSeconds'],
+            'Version'=>'2018-08-13',
+            'Name'=> 'cos',
+            'Region'=> 'ap-guangzhou',
+            'Policy'=> urlencode($policyStr)
+        );
+        $params['Signature'] = $this->getSignature($params, $config['secretKey'], $Method, $config);
+        $url = $config['url'];
+        $ch = curl_init($url);
+        if(array_key_exists('proxy', $config)){
+            $config['proxy'] && curl_setopt($ch, CURLOPT_PROXY, $config['proxy']);
+        }
+        curl_setopt($ch, CURLOPT_HEADER, 0);
+        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,0);
+        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0);
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+        curl_setopt($ch, CURLOPT_POST, 1);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $this->json2str($params));
+        $result = curl_exec($ch);
+        if(curl_errno($ch)) $result = curl_error($ch);
+        curl_close($ch);
+        $result = json_decode($result, 1);
+        if (isset($result['Response'])) {
+            $result = $result['Response'];
+            $result['startTime'] = $result['ExpiredTime'] - $config['durationSeconds'];
+        }
+        $result = $this->backwardCompat($result);
+        return $result;
+    }
+
+    // get policy
+    function getPolicy($scopes){
+        if (!is_array($scopes)){
+            return null;
+        }
+        $statements = array();
+
+        for($i=0, $counts=count($scopes); $i < $counts; $i++){
+            $actions=array();
+            $resources = array();
+            array_push($actions, $scopes[$i]->get_action());
+            array_push($resources, $scopes[$i]->get_resource());
+            $principal = array(
+                'qcs' => array('*')
+            );
+            $statement = array(
+                'actions' => $actions,
+                'effect' => 'allow',
+                'principal' => $principal,
+                'resource' => $resources
+            );
+            array_push($statements, $statement);
+        }
+
+        $policy = array(
+            'version' => '2.0',
+            'statement' => $statements
+        );
+        return $policy;
+    }
+}
+
+class Scope{
+    var $action;
+    var $bucket;
+    var $region;
+    var $resourcePrefix;
+    function __construct($action, $bucket, $region, $resourcePrefix){
+        $this->action = $action;
+        $this->bucket = $bucket;
+        $this->region = $region;
+        $this->resourcePrefix = $resourcePrefix;
+    }
+    function get_action(){
+        return $this->action;
+    }
+
+    function get_resource(){
+        $index = strripos($this->bucket, '-');
+        $bucketName = substr($this->bucket, 0, $index);
+        $appid = substr($this->bucket, $index + 1);
+        if(!(strpos($this->resourcePrefix, '/') === 0)){
+            $this->resourcePrefix = '/' . $this->resourcePrefix;
+        }
+        return 'qcs::cos:' . $this->region . ':uid/' . $appid . ':prefix//' . $appid . '/' . $bucketName . $this->resourcePrefix;
+    }
+}
+?>

+ 263 - 0
node_modules/cos-js-sdk-v5/server/sts.js

@@ -0,0 +1,263 @@
+// 临时密钥服务例子
+var bodyParser = require('body-parser');
+var STS = require('qcloud-cos-sts');
+var express = require('express');
+var crypto = require('crypto');
+var pathLib = require('path');
+var fs = require('fs');
+
+// 配置参数
+var config = {
+    secretId: process.env.SecretId,
+    secretKey: process.env.SecretKey,
+    proxy: process.env.Proxy,
+    durationSeconds: 1800,
+    bucket: process.env.Bucket,
+    region: process.env.Region,
+    // 允许操作(上传)的对象前缀,可以根据自己网站的用户登录态判断允许上传的目录,例子: user1/* 或者 * 或者a.jpg
+    // 请注意当使用 * 时,可能存在安全风险,详情请参阅:https://cloud.tencent.com/document/product/436/40265
+    allowPrefix: '_ALLOW_DIR_/*',
+    // 密钥的权限列表
+    allowActions: [
+        // 所有 action 请看文档 https://cloud.tencent.com/document/product/436/31923
+        // 简单上传
+        'name/cos:PutObject',
+        'name/cos:PostObject',
+        // 分片上传
+        'name/cos:InitiateMultipartUpload',
+        'name/cos:ListMultipartUploads',
+        'name/cos:ListParts',
+        'name/cos:UploadPart',
+        'name/cos:CompleteMultipartUpload'
+    ],
+};
+
+// 创建临时密钥服务和用于调试的静态服务
+var app = express();
+
+var replaceBucketRegion = (filePath) => {
+    return (req, res, next) => {
+        var content = fs.readFileSync(filePath).toString()
+            .replace(/(var config = {\r?\n *Bucket: ')test-1250000000(',\r?\n *Region: ')ap-guangzhou(',?\r?\n};?)/,
+            '$1' + config.bucket + '$2' + config.region +'$3');
+        content = content.replace("config.Uin = '10001';", "config.Uin = '" + process.env.Uin + "'");
+        res.header('Content-Type', 'application/javascript');
+        res.send(content);
+    };
+};
+app.use('/demo/demo.js', replaceBucketRegion(pathLib.resolve(__dirname, '../demo/demo.js')));
+app.use('/test/test.js', replaceBucketRegion(pathLib.resolve(__dirname, '../test/test.js')));
+app.use('/dist/', express.static(pathLib.resolve(__dirname, '../dist')));
+app.use('/demo/', express.static(pathLib.resolve(__dirname, '../demo')));
+app.use('/test/', express.static(pathLib.resolve(__dirname, '../test')));
+app.all('/', (req, res, next) => res.redirect('/demo/'));
+app.use(bodyParser.json());
+
+// 格式一:临时密钥接口
+app.all('/sts', function (req, res, next) {
+
+    // TODO 这里根据自己业务需要做好放行判断
+    if (config.allowPrefix === '_ALLOW_DIR_/*') {
+        res.send({error: '请修改 allowPrefix 配置项,指定允许上传的路径前缀'});
+        return;
+    }
+
+    // 获取临时密钥
+    var LongBucketName = config.bucket;
+    var ShortBucketName = LongBucketName.substr(0, LongBucketName.lastIndexOf('-'));
+    var AppId = LongBucketName.substr(LongBucketName.lastIndexOf('-') + 1);
+    // 数据万象DescribeMediaBuckets接口需要resource为*,参考 https://cloud.tencent.com/document/product/460/41741
+    var policy = {
+        'version': '2.0',
+        'statement': [{
+            'action': config.allowActions,
+            'effect': 'allow',
+            'resource': [
+                'qcs::cos:' + config.region + ':uid/' + AppId + ':prefix//' + AppId + '/' + ShortBucketName + '/' + config.allowPrefix,
+            ],
+        }],
+    };
+    var startTime = Math.round(Date.now() / 1000);
+    STS.getCredential({
+        secretId: config.secretId,
+        secretKey: config.secretKey,
+        proxy: config.proxy,
+        region: config.region,
+        durationSeconds: config.durationSeconds,
+        policy: policy,
+    }, function (err, tempKeys) {
+        if (tempKeys) tempKeys.startTime = startTime;
+        res.send(err || tempKeys);
+    });
+});
+
+// // 格式二:临时密钥接口,支持细粒度权限控制
+// // 判断是否允许获取密钥
+// var allowScope = function (scope) {
+//     var allow = (scope || []).every(function (item) {
+//         return config.allowActions.includes(item.action) &&
+//             item.bucket === config.bucket &&
+//             item.region === config.region &&
+//             (item.prefix || '').startsWith(config.allowPrefix);
+//     });
+//     return allow;
+// };
+// app.all('/sts-scope', function (req, res, next) {
+//     var scope = req.body;
+//
+//     // TODO 这里根据自己业务需要做好放行判断
+//     if (config.allowPrefix === '_ALLOW_DIR_/*') {
+//         res.send({error: '请修改 allowPrefix 配置项,指定允许上传的路径前缀'});
+//         return;
+//     }
+//     // TODO 这里可以判断 scope 细粒度控制权限
+//     if (!scope || !scope.length || !allowScope(scope)) return res.send({error: 'deny'});
+//
+//     // 获取临时密钥
+//     var policy = STS.getPolicy(scope);
+//     var startTime = Math.round(Date.now() / 1000);
+//     STS.getCredential({
+//         secretId: config.secretId,
+//         secretKey: config.secretKey,
+//         proxy: config.proxy,
+//         durationSeconds: config.durationSeconds,
+//         policy: policy,
+//     }, function (err, tempKeys) {
+//         if (tempKeys) tempKeys.startTime = startTime;
+//         res.send(err || tempKeys);
+//     });
+// });
+//
+// // 用于 PostObject 签名保护
+// app.all('/post-policy', function (req, res, next) {
+//     var query = req.query;
+//     var now = Math.round(Date.now() / 1000);
+//     var exp = now + 900;
+//     var qKeyTime = now + ';' + exp;
+//     var qSignAlgorithm = 'sha1';
+//     var policy = JSON.stringify({
+//         'expiration': new Date(exp * 1000).toISOString(),
+//         'conditions': [
+//             // {'acl': query.ACL},
+//             // ['starts-with', '$Content-Type', 'image/'],
+//             // ['starts-with', '$success_action_redirect', redirectUrl],
+//             // ['eq', '$x-cos-server-side-encryption', 'AES256'],
+//             {'q-sign-algorithm': qSignAlgorithm},
+//             {'q-ak': config.secretId},
+//             {'q-sign-time': qKeyTime},
+//             {'bucket': config.bucket},
+//             {'key': query.key},
+//         ]
+//     });
+//
+//     // 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
+//     // 步骤一:生成 SignKey
+//     var signKey = crypto.createHmac('sha1', config.secretKey).update(qKeyTime).digest('hex');
+//
+//     // 步骤二:生成 StringToSign
+//     var stringToSign = crypto.createHash('sha1').update(policy).digest('hex');
+//
+//     // 步骤三:生成 Signature
+//     var qSignature = crypto.createHmac('sha1', signKey).update(stringToSign).digest('hex');
+//
+//     console.log(policy);
+//     res.send({
+//         policyObj: JSON.parse(policy),
+//         policy: Buffer.from(policy).toString('base64'),
+//         qSignAlgorithm: qSignAlgorithm,
+//         qAk: config.secretId,
+//         qKeyTime: qKeyTime,
+//         qSignature: qSignature,
+//         // securityToken: securityToken, // 如果使用临时密钥,要返回在这个资源 sessionToken 的值
+//     });
+// });
+//
+// // 上传限制 Content-Type 示例,对应示例 demo/mime-limit.html
+// var COS = require('cos-nodejs-sdk-v5');
+// var cos = new COS({
+//     SecretId: config.secretId,
+//     SecretKey: config.secretKey,
+// });
+// app.post('/uploadSign', function (req, res, next) {
+//
+//     var T = function (x, n) {
+//         return ('0000' + x).slice(-(n || 2));
+//     }
+//     var guid = function () {
+//         var S4 = () => (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+//         return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+//     }
+//
+//     // 后端来决定文件名,安全性更高
+//     var filename = req.query.filename; // 前端传文件原名,后端来决定上传路径
+//     var ext = pathLib.extname(filename);
+//     var d = new Date();
+//     var key = `images/${d.getFullYear()}/${T(d.getMonth() + 1)}/${T(d.getDate())}/${guid()}${ext}`;
+//
+//     // 计算前端可能会用到的多个签名,x-cos-mime-limit: text/plain;img/jpg;img/*
+//     var signMap = {};
+//     var expires = 7200;
+//     var mimeLimit = 'image/*';
+//     var host = `${config.bucket}.cos.${config.region}.myqcloud.com`;
+//     // 1. ListMultipartUploads 签名
+//     signMap.ListMultipartUploads = cos.getAuth({
+//         Method: 'GET',
+//         Key: '',
+//         Expires: expires,
+//         Query: { uploads: '', prefix: key },
+//         Headers: { host: host },
+//     });
+//     // 2. ListParts 签名
+//     signMap.ListParts = cos.getAuth({
+//         Method: 'GET',
+//         Key: key,
+//         Expires: expires,
+//         Headers: { host: host },
+//     });
+//     // 3. InitiateMultipartUpload 签名
+//     signMap.InitiateMultipartUpload = cos.getAuth({
+//         Method: 'POST',
+//         Key: key,
+//         Expires: expires,
+//         Query: { uploads: '' },
+//         Headers: { host: host },
+//     });
+//     // 4. UploadPart 签名
+//     signMap.UploadPart = cos.getAuth({
+//         Method: 'PUT',
+//         Key: key,
+//         Expires: expires,
+//         Headers: { host: host, 'x-cos-mime-limit': mimeLimit },
+//     });
+//     // 5. CompleteMultipartUpload 签名
+//     signMap.CompleteMultipartUpload = cos.getAuth({
+//         Method: 'POST',
+//         Key: key,
+//         Expires: expires,
+//         Headers: { host: host },
+//     });
+//     // 6. PutObject 签名
+//     signMap.PutObject = cos.getAuth({
+//         Method: 'PUT',
+//         Key: key,
+//         Expires: expires,
+//         Headers: { host: host, 'x-cos-mime-limit': mimeLimit },
+//     });
+//     res.send({
+//         code: 0,
+//         host,
+//         signMap,
+//         bucket: config.bucket,
+//         region: config.region,
+//         key,
+//         mimeLimit,
+//     });
+// });
+
+app.all('*', function (req, res, next) {
+    res.send({code: -1, message: '404 Not Found'});
+});
+
+// 启动签名服务
+app.listen(3000);
+console.log('app is listening at http://127.0.0.1:3000');

+ 40 - 0
node_modules/cos-js-sdk-v5/server/sts.php

@@ -0,0 +1,40 @@
+<?php
+// 临时密钥计算样例
+
+include './qcloud-sts-sdk.php'; // 这里获取 sts.php https://github.com/tencentyun/qcloud-cos-sts-sdk/blob/master/php/sts/sts.php
+$sts = new STS();
+// 配置参数
+$config = array(
+    'url' => 'https://sts.tencentcloudapi.com/',
+    'domain' => 'sts.tencentcloudapi.com',
+    'proxy' => '',
+    'secretId' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 固定密钥
+    'secretKey' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // 固定密钥
+    'bucket' => 'test-1250000000', // 换成你的 bucket
+    'region' => 'ap-guangzhou', // 换成 bucket 所在园区
+    'durationSeconds' => 1800, // 密钥有效期
+    // 允许操作(上传)的对象前缀,可以根据自己网站的用户登录态判断允许上传的目录,例子: user1/* 或者 * 或者a.jpg
+    // 请注意当使用 * 时,可能存在安全风险,详情请参阅:https://cloud.tencent.com/document/product/436/40265
+    'allowPrefix' => '_ALLOW_DIR_/*',
+    // 密钥的权限列表。简单上传和分片需要以下的权限,其他权限列表请看 https://cloud.tencent.com/document/product/436/31923
+    'allowActions' => array (
+        // 所有 action 请看文档 https://cloud.tencent.com/document/product/436/31923
+        // 简单上传
+        'name/cos:PutObject',
+        'name/cos:PostObject',
+        // 分片上传
+        'name/cos:InitiateMultipartUpload',
+        'name/cos:ListMultipartUploads',
+        'name/cos:ListParts',
+        'name/cos:UploadPart',
+        'name/cos:CompleteMultipartUpload'
+    )
+);
+// 获取临时密钥,计算签名
+$tempKeys = $sts->getTempKeys($config);
+
+// 返回数据给前端
+header('Content-Type: application/json');
+header('Access-Control-Allow-Origin: http://127.0.0.1'); // 这里修改允许跨域访问的网站
+header('Access-Control-Allow-Headers: origin,accept,content-type');
+echo json_encode($tempKeys);

Разница между файлами не показана из-за своего большого размера
+ 1184 - 0
node_modules/cos-js-sdk-v5/src/advance.js


+ 60 - 0
node_modules/cos-js-sdk-v5/src/async.js

@@ -0,0 +1,60 @@
+var eachLimit = function (arr, limit, iterator, callback) {
+    callback = callback || function () {};
+    if (!arr.length || limit <= 0) {
+        return callback();
+    }
+
+    var completed = 0;
+    var started = 0;
+    var running = 0;
+
+    (function replenish () {
+        if (completed >= arr.length) {
+            return callback();
+        }
+
+        while (running < limit && started < arr.length) {
+            started += 1;
+            running += 1;
+            iterator(arr[started - 1], function (err) {
+
+                if (err) {
+                    callback(err);
+                    callback = function () {};
+                } else {
+                    completed += 1;
+                    running -= 1;
+                    if (completed >= arr.length) {
+                        callback();
+                    } else {
+                        replenish();
+                    }
+                }
+            });
+        }
+    })();
+};
+
+var retry = function (times, iterator, callback) {
+    var next = function (index) {
+        iterator(function (err, data) {
+            if (err && index < times) {
+                next(index + 1);
+            } else {
+                callback(err, data);
+            }
+        });
+    };
+    if (times < 1) {
+        callback();
+    } else {
+        next(1);
+    }
+};
+
+var async = {
+    eachLimit: eachLimit,
+    retry: retry
+};
+
+module.exports = async;

Разница между файлами не показана из-за своего большого размера
+ 3723 - 0
node_modules/cos-js-sdk-v5/src/base.js


+ 74 - 0
node_modules/cos-js-sdk-v5/src/cos.js

@@ -0,0 +1,74 @@
+'use strict';
+
+var util = require('./util');
+var event = require('./event');
+var task = require('./task');
+var base = require('./base');
+var advance = require('./advance');
+
+var defaultOptions = {
+    AppId: '', // AppId 已废弃,请拼接到 Bucket 后传入,例如:test-1250000000
+    SecretId: '',
+    SecretKey: '',
+    SecurityToken: '', // 使用临时密钥需要注意自行刷新 Token
+    ChunkRetryTimes: 2,
+    FileParallelLimit: 3,
+    ChunkParallelLimit: 3,
+    ChunkSize: 1024 * 1024,
+    SliceSize: 1024 * 1024,
+    CopyChunkParallelLimit: 20,
+    CopyChunkSize: 1024 * 1024 * 10,
+    CopySliceSize: 1024 * 1024 * 10,
+    MaxPartNumber: 10000,
+    ProgressInterval: 1000,
+    Domain: '',
+    ServiceDomain: '',
+    Protocol: '',
+    CompatibilityMode: false,
+    ForcePathStyle: false,
+    UseRawKey: false,
+    Timeout: 0, // 单位毫秒,0 代表不设置超时时间
+    CorrectClockSkew: true,
+    SystemClockOffset: 0, // 单位毫秒,ms
+    UploadCheckContentMd5: false,
+    UploadQueueSize: 10000,
+    UploadAddMetaMd5: false,
+    UploadIdCacheLimit: 50,
+    UseAccelerate: false,
+};
+
+// 对外暴露的类
+var COS = function (options) {
+    this.options = util.extend(util.clone(defaultOptions), options || {});
+    this.options.FileParallelLimit = Math.max(1, this.options.FileParallelLimit);
+    this.options.ChunkParallelLimit = Math.max(1, this.options.ChunkParallelLimit);
+    this.options.ChunkRetryTimes = Math.max(0, this.options.ChunkRetryTimes);
+    this.options.ChunkSize = Math.max(1024 * 1024, this.options.ChunkSize);
+    this.options.CopyChunkParallelLimit = Math.max(1, this.options.CopyChunkParallelLimit);
+    this.options.CopyChunkSize = Math.max(1024 * 1024, this.options.CopyChunkSize);
+    this.options.CopySliceSize = Math.max(0, this.options.CopySliceSize);
+    this.options.MaxPartNumber = Math.max(1024, Math.min(10000, this.options.MaxPartNumber));
+    this.options.Timeout = Math.max(0, this.options.Timeout);
+    if (this.options.AppId) {
+        console.warn('warning: AppId has been deprecated, Please put it at the end of parameter Bucket(E.g: "test-1250000000").');
+    }
+    if (util.isNode()) {
+      console.warn('warning: cos-js-sdk-v5 不支持 nodejs 环境使用,请改用 cos-nodejs-sdk-v5,参考文档: https://cloud.tencent.com/document/product/436/8629');
+      console.warn('warning: cos-js-sdk-v5 does not support nodejs environment. Please use cos-nodejs-sdk-v5 instead. See: https://cloud.tencent.com/document/product/436/8629');
+    }
+    event.init(this);
+    task.init(this);
+};
+
+base.init(COS, task);
+advance.init(COS, task);
+
+COS.util = {
+    md5: util.md5,
+    xml2json: util.xml2json,
+    json2xml: util.json2xml,
+};
+COS.getAuthorization = util.getAuth;
+COS.version = '1.3.1';
+
+module.exports = COS;

+ 34 - 0
node_modules/cos-js-sdk-v5/src/event.js

@@ -0,0 +1,34 @@
+var initEvent = function (cos) {
+    var listeners = {};
+    var getList = function (action) {
+        !listeners[action] && (listeners[action] = []);
+        return listeners[action];
+    };
+    cos.on = function (action, callback) {
+        if (action === 'task-list-update') {
+            console.warn('warning: Event "' + action + '" has been deprecated. Please use "list-update" instead.');
+        }
+        getList(action).push(callback);
+    };
+    cos.off = function (action, callback) {
+        var list = getList(action);
+        for (var i = list.length - 1; i >= 0; i--) {
+            callback === list[i] && list.splice(i, 1);
+        }
+    };
+    cos.emit = function (action, data) {
+        var list = getList(action).map(function (cb) {
+            return cb;
+        });
+        for (var i = 0; i < list.length; i++) {
+            list[i](data);
+        }
+    };
+};
+
+var EventProxy = function () {
+    initEvent(this);
+};
+
+module.exports.init = initEvent;
+module.exports.EventProxy = EventProxy;

+ 104 - 0
node_modules/cos-js-sdk-v5/src/session.js

@@ -0,0 +1,104 @@
+var util = require('./util');
+
+// 按照文件特征值,缓存 UploadId
+var cacheKey = 'cos_sdk_upload_cache';
+var expires = 30 * 24 * 3600;
+var cache;
+var timer;
+
+var getCache = function () {
+    try {
+        var val = JSON.parse(localStorage.getItem(cacheKey));
+    } catch (e) {
+    }
+    if (!val) val = [];
+    cache = val;
+};
+var setCache = function () {
+    try {
+        localStorage.setItem(cacheKey, JSON.stringify(cache))
+    } catch (e) {
+    }
+};
+
+var init = function () {
+    if (cache) return;
+    getCache.call(this);
+    // 清理太老旧的数据
+    var changed = false;
+    var now = Math.round(Date.now() / 1000);
+    for (var i = cache.length - 1; i >= 0; i--) {
+        var mtime = cache[i][2];
+        if (!mtime || mtime + expires < now) {
+            cache.splice(i, 1);
+            changed = true;
+        }
+    }
+    changed && setCache();
+};
+
+// 把缓存存到本地
+var save = function () {
+    if (timer) return;
+    timer = setTimeout(function () {
+        setCache();
+        timer = null;
+    }, 400);
+};
+
+var mod = {
+    using: {},
+    // 标记 UploadId 正在使用
+    setUsing: function (uuid) {
+        mod.using[uuid] = true;
+    },
+    // 标记 UploadId 已经没在使用
+    removeUsing: function (uuid) {
+        delete mod.using[uuid];
+    },
+    // 用上传参数生成哈希值
+    getFileId: function (file, ChunkSize, Bucket, Key) {
+        if (file.name && file.size && file.lastModifiedDate && ChunkSize) {
+            return util.md5([file.name, file.size, file.lastModifiedDate, ChunkSize, Bucket, Key].join('::'));
+        } else {
+            return null;
+        }
+    },
+    // 获取文件对应的 UploadId 列表
+    getUploadIdList: function (uuid) {
+        if (!uuid) return null;
+        init.call(this);
+        var list = [];
+        for (var i = 0; i < cache.length; i++) {
+            if (cache[i][0] === uuid)
+                list.push(cache[i][1]);
+        }
+        return list.length ? list : null;
+    },
+    // 缓存 UploadId
+    saveUploadId: function (uuid, UploadId, limit) {
+        init.call(this);
+        if (!uuid) return;
+        // 清理没用的 UploadId,js 文件没有 FilePath ,只清理相同记录
+        for (var i = cache.length - 1; i >= 0; i--) {
+            var item = cache[i];
+            if (item[0] === uuid && item[1] === UploadId) {
+                cache.splice(i, 1);
+            }
+        }
+        cache.unshift([uuid, UploadId, Math.round(Date.now() / 1000)]);
+        if (cache.length > limit) cache.splice(limit);
+        save();
+    },
+    // UploadId 已用完,移除掉
+    removeUploadId: function (UploadId) {
+        init.call(this);
+        delete mod.using[UploadId];
+        for (var i = cache.length - 1; i >= 0; i--) {
+            if (cache[i][1] === UploadId) cache.splice(i, 1)
+        }
+        save();
+    },
+};
+
+module.exports = mod;

+ 255 - 0
node_modules/cos-js-sdk-v5/src/task.js

@@ -0,0 +1,255 @@
+var session = require('./session');
+var util = require('./util');
+
+var originApiMap = {};
+var transferToTaskMethod = function (apiMap, apiName) {
+    originApiMap[apiName] = apiMap[apiName];
+    apiMap[apiName] = function (params, callback) {
+        if (params.SkipTask) {
+            originApiMap[apiName].call(this, params, callback);
+        } else {
+            this._addTask(apiName, params, callback);
+        }
+    };
+};
+
+var initTask = function (cos) {
+
+    var queue = [];
+    var tasks = {};
+    var uploadingFileCount = 0;
+    var nextUploadIndex = 0;
+
+    // 接口返回简略的任务信息
+    var formatTask = function (task) {
+        var t = {
+            id: task.id,
+            Bucket: task.Bucket,
+            Region: task.Region,
+            Key: task.Key,
+            FilePath: task.FilePath,
+            state: task.state,
+            loaded: task.loaded,
+            size: task.size,
+            speed: task.speed,
+            percent: task.percent,
+            hashPercent: task.hashPercent,
+            error: task.error,
+        };
+        if (task.FilePath) t.FilePath = task.FilePath;
+        if (task._custom) t._custom = task._custom; // 控制台使用
+        return t;
+    };
+
+    var emitListUpdate = (function () {
+        var timer;
+        var emit = function () {
+            timer = 0;
+            cos.emit('task-list-update', {list: util.map(queue, formatTask)});
+            cos.emit('list-update', {list: util.map(queue, formatTask)});
+        };
+        return function () {
+            if (!timer) timer = setTimeout(emit);
+        }
+    })();
+
+    var clearQueue = function () {
+        if (queue.length <= cos.options.UploadQueueSize) return;
+        for (var i = 0;
+             i < nextUploadIndex && // 小于当前操作的 index 才清理
+             i < queue.length && // 大于队列才清理
+             queue.length > cos.options.UploadQueueSize // 如果还太多,才继续清理
+            ;) {
+            var isActive = queue[i].state === 'waiting' || queue[i].state === 'checking' || queue[i].state === 'uploading';
+            if (!queue[i] || !isActive) {
+                tasks[queue[i].id] && (delete tasks[queue[i].id]);
+                queue.splice(i, 1);
+                nextUploadIndex--;
+            } else {
+                i++;
+            }
+        }
+        emitListUpdate();
+    };
+
+    var startNextTask = function () {
+        // 检查是否允许增加执行进程
+        if (uploadingFileCount >= cos.options.FileParallelLimit) return;
+        // 跳过不可执行的任务
+        while (queue[nextUploadIndex] && queue[nextUploadIndex].state !== 'waiting') nextUploadIndex++;
+        // 检查是否已遍历结束
+        if (nextUploadIndex >= queue.length) return;
+        // 上传该遍历到的任务
+        var task = queue[nextUploadIndex];
+        nextUploadIndex++;
+        uploadingFileCount++;
+        task.state = 'checking';
+        task.params.onTaskStart && task.params.onTaskStart(formatTask(task));
+        !task.params.UploadData && (task.params.UploadData = {});
+        var apiParams = util.formatParams(task.api, task.params);
+        originApiMap[task.api].call(cos, apiParams, function (err, data) {
+            if (!cos._isRunningTask(task.id)) return;
+            if (task.state === 'checking' || task.state === 'uploading') {
+                task.state = err ? 'error' : 'success';
+                err && (task.error = err);
+                uploadingFileCount--;
+                emitListUpdate();
+                startNextTask();
+                task.callback && task.callback(err, data);
+                if (task.state === 'success') {
+                    if (task.params) {
+                        delete task.params.UploadData;
+                        delete task.params.Body;
+                        delete task.params;
+                    }
+                    delete task.callback;
+                }
+            }
+            clearQueue();
+        });
+        emitListUpdate();
+        // 异步执行下一个任务
+        setTimeout(startNextTask);
+    };
+
+    var killTask = function (id, switchToState) {
+        var task = tasks[id];
+        if (!task) return;
+        var waiting = task && task.state === 'waiting';
+        var running = task && (task.state === 'checking' || task.state === 'uploading');
+        if (switchToState === 'canceled' && task.state !== 'canceled' ||
+            switchToState === 'paused' && waiting ||
+            switchToState === 'paused' && running) {
+            if (switchToState === 'paused' && task.params.Body && typeof task.params.Body.pipe === 'function') {
+                console.error('stream not support pause');
+                return;
+            }
+            task.state = switchToState;
+            cos.emit('inner-kill-task', {TaskId: id, toState: switchToState});
+            try {
+                var UploadId = task && task.params && task.params.UploadData.UploadId
+            } catch(e) {}
+            if (switchToState === 'canceled' && UploadId) session.removeUsing(UploadId)
+            emitListUpdate();
+            if (running) {
+                uploadingFileCount--;
+                startNextTask();
+            }
+            if (switchToState === 'canceled') {
+                if (task.params) {
+                    delete task.params.UploadData;
+                    delete task.params.Body;
+                    delete task.params;
+                }
+                delete task.callback;
+            }
+        }
+        clearQueue();
+    };
+
+    cos._addTasks = function (taskList) {
+        util.each(taskList, function (task) {
+            cos._addTask(task.api, task.params, task.callback, true);
+        });
+        emitListUpdate();
+    };
+
+    var isTaskReadyWarning = true;
+    cos._addTask = function (api, params, callback, ignoreAddEvent) {
+
+        // 复制参数对象
+        params = util.formatParams(api, params);
+
+        // 生成 id
+        var id = util.uuid();
+        params.TaskId = id;
+        params.onTaskReady && params.onTaskReady(id);
+        if (params.TaskReady) {
+            params.TaskReady(id);
+            isTaskReadyWarning && console.warn('warning: Param "TaskReady" has been deprecated. Please use "onTaskReady" instead.');
+            isTaskReadyWarning = false;
+        }
+
+        var task = {
+            // env
+            params: params,
+            callback: callback,
+            api: api,
+            index: queue.length,
+            // task
+            id: id,
+            Bucket: params.Bucket,
+            Region: params.Region,
+            Key: params.Key,
+            FilePath: params.FilePath || '',
+            state: 'waiting',
+            loaded: 0,
+            size: 0,
+            speed: 0,
+            percent: 0,
+            hashPercent: 0,
+            error: null,
+            _custom: params._custom,
+        };
+        var onHashProgress = params.onHashProgress;
+        params.onHashProgress = function (info) {
+            if (!cos._isRunningTask(task.id)) return;
+            task.hashPercent = info.percent;
+            onHashProgress && onHashProgress(info);
+            emitListUpdate();
+        };
+        var onProgress = params.onProgress;
+        params.onProgress = function (info) {
+            if (!cos._isRunningTask(task.id)) return;
+            task.state === 'checking' && (task.state = 'uploading');
+            task.loaded = info.loaded;
+            task.speed = info.speed;
+            task.percent = info.percent;
+            onProgress && onProgress(info);
+            emitListUpdate();
+        };
+
+        // 异步获取 filesize
+        util.getFileSize(api, params, function (err, size) {
+            // 开始处理上传
+            if (err) return callback(util.error(err)); // 如果获取大小出错,不加入队列
+            // 获取完文件大小再把任务加入队列
+            tasks[id] = task;
+            queue.push(task);
+            task.size = size;
+            !ignoreAddEvent && emitListUpdate();
+            startNextTask();
+            clearQueue();
+        });
+        return id;
+    };
+    cos._isRunningTask = function (id) {
+        var task = tasks[id];
+        return !!(task && (task.state === 'checking' || task.state === 'uploading'));
+    };
+    cos.getTaskList = function () {
+        return util.map(queue, formatTask);
+    };
+    cos.cancelTask = function (id) {
+        killTask(id, 'canceled');
+    };
+    cos.pauseTask = function (id) {
+        killTask(id, 'paused');
+    };
+    cos.restartTask = function (id) {
+        var task = tasks[id];
+        if (task && (task.state === 'paused' || task.state === 'error')) {
+            task.state = 'waiting';
+            emitListUpdate();
+            nextUploadIndex = Math.min(nextUploadIndex, task.index);
+            startNextTask();
+        }
+    };
+    cos.isUploadRunning = function () {
+        return uploadingFileCount || nextUploadIndex < queue.length;
+    };
+
+};
+
+module.exports.transferToTaskMethod = transferToTaskMethod;
+module.exports.init = initTask;

+ 724 - 0
node_modules/cos-js-sdk-v5/src/util.js

@@ -0,0 +1,724 @@
+'use strict';
+
+var md5 = require('../lib/md5');
+var CryptoJS = require('../lib/crypto');
+var xml2json = require('../lib/xml2json');
+var json2xml = require('../lib/json2xml');
+
+function camSafeUrlEncode(str) {
+    return encodeURIComponent(str)
+        .replace(/!/g, '%21')
+        .replace(/'/g, '%27')
+        .replace(/\(/g, '%28')
+        .replace(/\)/g, '%29')
+        .replace(/\*/g, '%2A');
+}
+
+function getObjectKeys(obj, forKey) {
+  var list = [];
+  for (var key in obj) {
+      if (obj.hasOwnProperty(key)) {
+          list.push(forKey ? camSafeUrlEncode(key).toLowerCase() : key);
+      }
+  }
+  return list.sort(function (a, b) {
+      a = a.toLowerCase();
+      b = b.toLowerCase();
+      return a === b ? 0 : (a > b ? 1 : -1);
+  });
+};
+
+var obj2str = function (obj) {
+  var i, key, val;
+  var list = [];
+  var keyList = getObjectKeys(obj);
+  for (i = 0; i < keyList.length; i++) {
+      key = keyList[i];
+      val = (obj[key] === undefined || obj[key] === null) ? '' : ('' + obj[key]);
+      key = camSafeUrlEncode(key).toLowerCase();
+      val = camSafeUrlEncode(val) || '';
+      list.push(key + '=' + val)
+  }
+  return list.join('&');
+};
+
+//测试用的key后面可以去掉
+var getAuth = function (opt) {
+    opt = opt || {};
+
+    var SecretId = opt.SecretId;
+    var SecretKey = opt.SecretKey;
+    var KeyTime = opt.KeyTime;
+    var method = (opt.method || opt.Method || 'get').toLowerCase();
+    var queryParams = clone(opt.Query || opt.params || {});
+    var headers = clone(opt.Headers || opt.headers || {});
+
+    var Key = opt.Key || '';
+    var pathname;
+    if (opt.UseRawKey) {
+        pathname = opt.Pathname || opt.pathname || '/' + Key;
+    } else {
+        pathname = opt.Pathname || opt.pathname || Key;
+        pathname.indexOf('/') !== 0 && (pathname = '/' + pathname);
+    }
+
+    if (!SecretId) throw new Error('missing param SecretId');
+    if (!SecretKey) throw new Error('missing param SecretKey');
+
+    // 签名有效起止时间
+    var now = Math.round(getSkewTime(opt.SystemClockOffset) / 1000) - 1;
+    var exp = now;
+
+    var Expires = opt.Expires || opt.expires;
+    if (Expires === undefined) {
+        exp += 900; // 签名过期时间为当前 + 900s
+    } else {
+        exp += (Expires * 1) || 0;
+    }
+
+    // 要用到的 Authorization 参数列表
+    var qSignAlgorithm = 'sha1';
+    var qAk = SecretId;
+    var qSignTime = KeyTime || now + ';' + exp;
+    var qKeyTime = KeyTime || now + ';' + exp;
+    var qHeaderList = getObjectKeys(headers).join(';').toLowerCase();
+    var qUrlParamList = getObjectKeys(queryParams).join(';').toLowerCase();
+
+    // 签名算法说明文档:https://www.qcloud.com/document/product/436/7778
+    // 步骤一:计算 SignKey
+    var signKey = CryptoJS.HmacSHA1(qKeyTime, SecretKey).toString();
+
+    // 步骤二:构成 FormatString
+    var formatString = [method, pathname, util.obj2str(queryParams), util.obj2str(headers), ''].join('\n');
+
+    // 步骤三:计算 StringToSign
+    var stringToSign = ['sha1', qSignTime, CryptoJS.SHA1(formatString).toString(), ''].join('\n');
+
+    // 步骤四:计算 Signature
+    var qSignature = CryptoJS.HmacSHA1(stringToSign, signKey).toString();
+
+    // 步骤五:构造 Authorization
+    var authorization = [
+        'q-sign-algorithm=' + qSignAlgorithm,
+        'q-ak=' + qAk,
+        'q-sign-time=' + qSignTime,
+        'q-key-time=' + qKeyTime,
+        'q-header-list=' + qHeaderList,
+        'q-url-param-list=' + qUrlParamList,
+        'q-signature=' + qSignature
+    ].join('&');
+
+    return authorization;
+
+};
+
+var readIntBE = function (chunk, size, offset) {
+    var bytes = size / 8;
+    var buf = chunk.slice(offset, offset + bytes);
+    new Uint8Array(buf).reverse();
+    return new ({8: Uint8Array, 16: Uint16Array, 32: Uint32Array})[size](buf)[0];
+};
+var buf2str = function (chunk, start, end, isUtf8) {
+    var buf = chunk.slice(start, end);
+    var str = '';
+    new Uint8Array(buf).forEach(function (charCode) {
+        str += String.fromCharCode(charCode)
+    });
+    if (isUtf8) str = decodeURIComponent(escape(str));
+    return str;
+};
+var parseSelectPayload = function (chunk) {
+    var header = {};
+    var body = buf2str(chunk);
+    var result = {records:[]};
+    while (chunk.byteLength) {
+        var totalLength = readIntBE(chunk, 32, 0);
+        var headerLength = readIntBE(chunk, 32, 4);
+        var payloadRestLength = totalLength - headerLength - 16;
+        var offset = 0;
+        var content;
+        chunk = chunk.slice(12);
+        // 获取 Message 的 header 信息
+        while (offset < headerLength) {
+            var headerNameLength = readIntBE(chunk, 8, offset);
+            var headerName = buf2str(chunk, offset + 1, offset + 1 + headerNameLength);
+            var headerValueLength = readIntBE(chunk, 16, offset + headerNameLength + 2);
+            var headerValue = buf2str(chunk, offset + headerNameLength + 4, offset + headerNameLength + 4 + headerValueLength);
+            header[headerName] = headerValue;
+            offset += headerNameLength + 4 + headerValueLength;
+        }
+        if (header[':event-type'] === 'Records') {
+            content = buf2str(chunk, offset, offset + payloadRestLength, true);
+            result.records.push(content);
+        } else if (header[':event-type'] === 'Stats') {
+            content = buf2str(chunk, offset, offset + payloadRestLength, true);
+            result.stats = util.xml2json(content).Stats;
+        } else if (header[':event-type'] === 'error') {
+            var errCode = header[':error-code'];
+            var errMessage = header[':error-message'];
+            var err = new Error(errMessage);
+            err.message = errMessage;
+            err.name = err.code = errCode;
+            result.error = err;
+        } else if (['Progress', 'Continuation', 'End'].includes(header[':event-type'])) {
+            // do nothing
+        }
+        chunk = chunk.slice(offset + payloadRestLength + 4);
+    }
+    return {
+        payload: result.records.join(''),
+        body: body,
+    };
+};
+
+var getSourceParams = function (source) {
+    var parser = this.options.CopySourceParser;
+    if (parser) return parser(source);
+    var m = source.match(/^([^.]+-\d+)\.cos(v6|-cdc)?\.([^.]+)\.myqcloud\.com\/(.+)$/);
+    if (!m) return null;
+    return { Bucket: m[1], Region: m[3], Key: m[4] };
+};
+
+var noop = function () {
+
+};
+
+// 清除对象里值为的 undefined 或 null 的属性
+var clearKey = function (obj) {
+    var retObj = {};
+    for (var key in obj) {
+        if (obj.hasOwnProperty(key) && obj[key] !== undefined && obj[key] !== null) {
+            retObj[key] = obj[key];
+        }
+    }
+    return retObj;
+};
+
+var readAsBinaryString = function (blob, callback) {
+    var readFun;
+    var fr = new FileReader();
+    if (FileReader.prototype.readAsBinaryString) {
+        readFun = FileReader.prototype.readAsBinaryString;
+        fr.onload = function () {
+            callback(this.result);
+        };
+    } else if (FileReader.prototype.readAsArrayBuffer) { // 在 ie11 添加 readAsBinaryString 兼容
+        readFun = function (fileData) {
+            var binary = "";
+            var pt = this;
+            var reader = new FileReader();
+            reader.onload = function (e) {
+                var bytes = new Uint8Array(reader.result);
+                var length = bytes.byteLength;
+                for (var i = 0; i < length; i++) {
+                    binary += String.fromCharCode(bytes[i]);
+                }
+                callback(binary);
+            };
+            reader.readAsArrayBuffer(fileData);
+        };
+    } else {
+        console.error('FileReader not support readAsBinaryString');
+    }
+    readFun.call(fr, blob);
+};
+
+var fileSliceNeedCopy = (function () {
+    var compareVersion = function(a, b) {
+        a = a.split('.');
+        b = b.split('.');
+        for (var i = 0; i < b.length; i++) {
+            if (a[i] !== b[i]) {
+                return parseInt(a[i]) > parseInt(b[i]) ? 1 : -1;
+            }
+        }
+        return 0;
+    };
+    var check = function (ua) {
+        var ChromeVersion = (ua.match(/Chrome\/([.\d]+)/) || [])[1];
+        var QBCoreVersion = (ua.match(/QBCore\/([.\d]+)/) || [])[1];
+        var QQBrowserVersion = (ua.match(/QQBrowser\/([.\d]+)/) || [])[1];
+        var need = ChromeVersion && compareVersion(ChromeVersion, '53.0.2785.116') < 0
+            && QBCoreVersion && compareVersion(QBCoreVersion, '3.53.991.400') < 0
+            && QQBrowserVersion && compareVersion(QQBrowserVersion, '9.0.2524.400') <= 0 || false;
+        return need;
+    };
+    return check(navigator && navigator.userAgent);
+})();
+
+// 获取文件分片
+var fileSlice = function (file, start, end, isUseToUpload, callback) {
+    var blob;
+    if (file.slice) {
+        blob = file.slice(start, end);
+    } else if (file.mozSlice) {
+        blob = file.mozSlice(start, end);
+    } else if (file.webkitSlice) {
+        blob = file.webkitSlice(start, end);
+    }
+    if (isUseToUpload && fileSliceNeedCopy) {
+        var reader = new FileReader();
+        reader.onload = function (e) {
+            blob = null;
+            callback(new Blob([reader.result]));
+        };
+        reader.readAsArrayBuffer(blob);
+    } else {
+        callback(blob);
+    }
+};
+
+// 获取文件内容的 MD5
+var getBodyMd5 = function (UploadCheckContentMd5, Body, callback, onProgress) {
+    callback = callback || noop;
+    if (UploadCheckContentMd5) {
+        if (typeof Body === 'string') {
+            callback(util.md5(Body, true));
+        } else if (Blob && Body instanceof Blob) {
+            util.getFileMd5(Body, function (err, md5) {
+                callback(md5);
+            }, onProgress);
+        } else {
+            callback();
+        }
+    } else {
+        callback();
+    }
+};
+
+// 获取文件 md5 值
+var md5ChunkSize = 1024 * 1024;
+var getFileMd5 = function (blob, callback, onProgress) {
+    var size = blob.size;
+    var loaded = 0;
+    var md5ctx = md5.getCtx();
+    var next = function (start) {
+        if (start >= size) {
+            var hash = md5ctx.digest('hex');
+            callback(null, hash);
+            return;
+        }
+        var end = Math.min(size, start + md5ChunkSize);
+        util.fileSlice(blob, start, end, false, function (chunk) {
+            readAsBinaryString(chunk, function (content) {
+                chunk = null;
+                md5ctx = md5ctx.update(content, true);
+                loaded += content.length;
+                content = null;
+                if (onProgress) onProgress({loaded: loaded, total: size, percent: Math.round(loaded / size * 10000) / 10000});
+                next(start + md5ChunkSize);
+            });
+        });
+    };
+    next(0);
+};
+
+function clone(obj) {
+    return map(obj, function (v) {
+        return typeof v === 'object' && v !== null ? clone(v) : v;
+    });
+}
+
+function attr(obj, name, defaultValue) {
+    return obj && name in obj ? obj[name] : defaultValue;
+}
+
+function extend(target, source) {
+    each(source, function (val, key) {
+        target[key] = source[key];
+    });
+    return target;
+}
+
+function isArray(arr) {
+    return arr instanceof Array;
+}
+
+function isInArray(arr, item) {
+    var flag = false;
+    for (var i = 0; i < arr.length; i++) {
+        if (item === arr[i]) {
+            flag = true;
+            break;
+        }
+    }
+    return flag;
+}
+
+function makeArray(arr) {
+    return isArray(arr) ? arr : [arr];
+}
+
+function each(obj, fn) {
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            fn(obj[i], i);
+        }
+    }
+}
+
+function map(obj, fn) {
+    var o = isArray(obj) ? [] : {};
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            o[i] = fn(obj[i], i);
+        }
+    }
+    return o;
+}
+
+function filter(obj, fn) {
+    var iaArr = isArray(obj);
+    var o = iaArr ? [] : {};
+    for (var i in obj) {
+        if (obj.hasOwnProperty(i)) {
+            if (fn(obj[i], i)) {
+                if (iaArr) {
+                    o.push(obj[i]);
+                } else {
+                    o[i] = obj[i];
+                }
+            }
+        }
+    }
+    return o;
+}
+
+var binaryBase64 = function (str) {
+    var i, len, char, res = '';
+    for (i = 0, len = str.length / 2; i < len; i++) {
+        char = parseInt(str[i * 2] + str[i * 2 + 1], 16);
+        res += String.fromCharCode(char);
+    }
+    return btoa(res);
+};
+var uuid = function () {
+    var S4 = function () {
+        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
+    };
+    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
+};
+
+var hasMissingParams = function (apiName, params) {
+    var Bucket = params.Bucket;
+    var Region = params.Region;
+    var Key = params.Key;
+    var Domain = this.options.Domain;
+    var checkBucket = !Domain || Domain.indexOf('{Bucket}') > -1;
+    var checkRegion = !Domain || Domain.indexOf('{Region}') > -1;
+    if (apiName.indexOf('Bucket') > -1 || apiName === 'deleteMultipleObject' || apiName === 'multipartList' || apiName === 'listObjectVersions') {
+        if (checkBucket && !Bucket) return 'Bucket';
+        if (checkRegion && !Region) return 'Region';
+    } else if (apiName.indexOf('Object') > -1 || apiName.indexOf('multipart') > -1 || apiName === 'sliceUploadFile' || apiName === 'abortUploadTask') {
+        if (checkBucket && !Bucket) return 'Bucket';
+        if (checkRegion && !Region) return 'Region';
+        if (!Key) return 'Key';
+    }
+    return false;
+};
+
+var formatParams = function (apiName, params) {
+
+    // 复制参数对象
+    params = extend({}, params);
+
+    // 统一处理 Headers
+    if (apiName !== 'getAuth' && apiName !== 'getV4Auth' && apiName !== 'getObjectUrl') {
+        var Headers = params.Headers || {};
+        if (params && typeof params === 'object') {
+            (function () {
+                for (var key in params) {
+                    if (params.hasOwnProperty(key) && key.indexOf('x-cos-') > -1) {
+                        Headers[key] = params[key];
+                    }
+                }
+            })();
+
+            var headerMap = {
+                // params headers
+                'x-cos-mfa': 'MFA',
+                'Content-MD5': 'ContentMD5',
+                'Content-Length': 'ContentLength',
+                'Content-Type': 'ContentType',
+                'Expect': 'Expect',
+                'Expires': 'Expires',
+                'Cache-Control': 'CacheControl',
+                'Content-Disposition': 'ContentDisposition',
+                'Content-Encoding': 'ContentEncoding',
+                'Range': 'Range',
+                'If-Modified-Since': 'IfModifiedSince',
+                'If-Unmodified-Since': 'IfUnmodifiedSince',
+                'If-Match': 'IfMatch',
+                'If-None-Match': 'IfNoneMatch',
+                'x-cos-copy-source': 'CopySource',
+                'x-cos-copy-source-Range': 'CopySourceRange',
+                'x-cos-metadata-directive': 'MetadataDirective',
+                'x-cos-copy-source-If-Modified-Since': 'CopySourceIfModifiedSince',
+                'x-cos-copy-source-If-Unmodified-Since': 'CopySourceIfUnmodifiedSince',
+                'x-cos-copy-source-If-Match': 'CopySourceIfMatch',
+                'x-cos-copy-source-If-None-Match': 'CopySourceIfNoneMatch',
+                'x-cos-acl': 'ACL',
+                'x-cos-grant-read': 'GrantRead',
+                'x-cos-grant-write': 'GrantWrite',
+                'x-cos-grant-full-control': 'GrantFullControl',
+                'x-cos-grant-read-acp': 'GrantReadAcp',
+                'x-cos-grant-write-acp': 'GrantWriteAcp',
+                'x-cos-storage-class': 'StorageClass',
+                'x-cos-traffic-limit': 'TrafficLimit',
+                'x-cos-mime-limit': 'MimeLimit',
+                // SSE-C
+                'x-cos-server-side-encryption-customer-algorithm': 'SSECustomerAlgorithm',
+                'x-cos-server-side-encryption-customer-key': 'SSECustomerKey',
+                'x-cos-server-side-encryption-customer-key-MD5': 'SSECustomerKeyMD5',
+                // SSE-COS、SSE-KMS
+                'x-cos-server-side-encryption': 'ServerSideEncryption',
+                'x-cos-server-side-encryption-cos-kms-key-id': 'SSEKMSKeyId',
+                'x-cos-server-side-encryption-context': 'SSEContext',
+            };
+            util.each(headerMap, function (paramKey, headerKey) {
+                if (params[paramKey] !== undefined) {
+                    Headers[headerKey] = params[paramKey];
+                }
+            });
+
+            params.Headers = clearKey(Headers);
+        }
+    }
+
+    return params;
+};
+
+var apiWrapper = function (apiName, apiFn) {
+    return function (params, callback) {
+
+        var self = this;
+
+        // 处理参数
+        if (typeof params === 'function') {
+            callback = params;
+            params = {};
+        }
+
+        // 整理参数格式
+        params = formatParams(apiName, params);
+
+        // 代理回调函数
+        var formatResult = function (result) {
+            if (result && result.headers) {
+                result.headers['x-cos-request-id'] && (result.RequestId = result.headers['x-cos-request-id']);
+                result.headers['x-cos-version-id'] && (result.VersionId = result.headers['x-cos-version-id']);
+                result.headers['x-cos-delete-marker'] && (result.DeleteMarker = result.headers['x-cos-delete-marker']);
+            }
+            return result;
+        };
+        var _callback = function (err, data) {
+            callback && callback(formatResult(err), formatResult(data));
+        };
+
+        var checkParams = function () {
+            if (apiName !== 'getService' && apiName !== 'abortUploadTask') {
+                // 判断参数是否完整
+                var missingResult = hasMissingParams.call(self, apiName, params)
+                if (missingResult) {
+                    return 'missing param ' + missingResult;
+                }
+                // 判断 region 格式
+                if (params.Region) {
+                    if (self.options.CompatibilityMode) {
+                        if (!/^([a-z\d-.]+)$/.test(params.Region)) {
+                            return 'Region format error.';
+                        }
+                    } else {
+                        if (params.Region.indexOf('cos.') > -1) {
+                            return 'param Region should not be start with "cos."';
+                        } else if (!/^([a-z\d-]+)$/.test(params.Region)) {
+                            return 'Region format error.';
+                        }
+                    }
+                    // 判断 region 格式
+                    if (!self.options.CompatibilityMode
+                        && params.Region.indexOf('-') === -1
+                        && params.Region !== 'yfb'
+                        && params.Region !== 'default'
+                        && params.Region !== 'accelerate' ) {
+                        console.warn('warning: param Region format error, find help here: https://cloud.tencent.com/document/product/436/6224');
+                    }
+                }
+                // 兼容不带 AppId 的 Bucket
+                if (params.Bucket) {
+                    if (!/^([a-z\d-]+)-(\d+)$/.test(params.Bucket)) {
+                        if (params.AppId) {
+                            params.Bucket = params.Bucket + '-' + params.AppId;
+                        } else if (self.options.AppId) {
+                            params.Bucket = params.Bucket + '-' + self.options.AppId;
+                        } else {
+                            return 'Bucket should format as "test-1250000000".';
+                        }
+                    }
+                    if (params.AppId) {
+                        console.warn('warning: AppId has been deprecated, Please put it at the end of parameter Bucket(E.g Bucket:"test-1250000000" ).');
+                        delete params.AppId;
+                    }
+                }
+                // 如果 Key 是 / 开头,强制去掉第一个 /
+                if (!self.options.UseRawKey && params.Key && params.Key.substr(0, 1) === '/') {
+                    params.Key = params.Key.substr(1);
+                }
+            }
+        };
+
+        var errMsg = checkParams();
+        var isSync = apiName === 'getAuth' || apiName === 'getObjectUrl';
+        if (window.Promise && !isSync && !callback) {
+            return new Promise(function (resolve, reject) {
+                callback = function (err, data) {
+                    err ? reject(err) : resolve(data);
+                };
+                if (errMsg) return _callback(util.error(new Error(errMsg)));
+                apiFn.call(self, params, _callback);
+            });
+        } else {
+            if (errMsg) return _callback(util.error(new Error(errMsg)));
+            var res = apiFn.call(self, params, _callback);
+            if (isSync) return res;
+        }
+    }
+};
+
+var throttleOnProgress = function (total, onProgress) {
+    var self = this;
+    var size0 = 0;
+    var size1 = 0;
+    var time0 = Date.now();
+    var time1;
+    var timer;
+
+    function update() {
+        timer = 0;
+        if (onProgress && (typeof onProgress === 'function')) {
+            time1 = Date.now();
+            var speed = Math.max(0, Math.round((size1 - size0) / ((time1 - time0) / 1000) * 100) / 100) || 0;
+            var percent;
+            if (size1 === 0 && total === 0) {
+                percent = 1;
+            } else {
+                percent = Math.floor(size1 / total * 100) / 100 || 0;
+            }
+            time0 = time1;
+            size0 = size1;
+            try {
+                onProgress({loaded: size1, total: total, speed: speed, percent: percent});
+            } catch (e) {
+            }
+        }
+    }
+
+    return function (info, immediately) {
+        if (info) {
+            size1 = info.loaded;
+            total = info.total;
+        }
+        if (immediately) {
+            clearTimeout(timer);
+            update();
+        } else {
+            if (timer) return;
+            timer = setTimeout(update, self.options.ProgressInterval);
+        }
+    };
+};
+
+var getFileSize = function (api, params, callback) {
+    var size;
+    if (typeof params.Body === 'string') {
+        params.Body = new Blob([params.Body], {type: 'text/plain'});
+    } else if (params.Body instanceof ArrayBuffer) {
+        params.Body = new Blob([params.Body]);
+    }
+    if ((params.Body && (params.Body instanceof Blob || params.Body.toString() === '[object File]' || params.Body.toString() === '[object Blob]'))) {
+        size = params.Body.size;
+    } else {
+        callback(util.error(new Error('params body format error, Only allow File|Blob|String.')));
+        return;
+    }
+    params.ContentLength = size;
+    callback(null, size);
+};
+
+// 获取调正的时间戳
+var getSkewTime = function (offset) {
+    return Date.now() + (offset || 0);
+};
+
+
+var error = function (err, opt) {
+    var sourceErr = err;
+    err.message = err.message || null;
+
+    if (typeof opt === 'string') {
+        err.error = opt;
+        err.message = opt;
+    } else if (typeof opt === 'object' && opt !== null) {
+        extend(err, opt);
+        if (opt.code || opt.name) err.code = opt.code || opt.name;
+        if (opt.message) err.message = opt.message;
+        if (opt.stack) err.stack = opt.stack;
+    }
+
+    if (typeof Object.defineProperty === 'function') {
+        Object.defineProperty(err, 'name', {writable: true, enumerable: false});
+        Object.defineProperty(err, 'message', {enumerable: true});
+    }
+
+    err.name = opt && opt.name || err.name || err.code || 'Error';
+    if (!err.code) err.code = err.name;
+    if (!err.error) err.error = clone(sourceErr); // 兼容老的错误格式
+
+    return err;
+}
+
+var isNode = function () {
+    return typeof window !== 'object' && typeof process === 'object' && typeof require === 'function';
+}
+
+var isCIHost = function(url) {
+    return /^https?:\/\/([^/]+\.)?ci\.[^/]+/.test(url);
+}
+
+var util = {
+    noop: noop,
+    formatParams: formatParams,
+    apiWrapper: apiWrapper,
+    xml2json: xml2json,
+    json2xml: json2xml,
+    md5: md5,
+    clearKey: clearKey,
+    fileSlice: fileSlice,
+    getBodyMd5: getBodyMd5,
+    getFileMd5: getFileMd5,
+    binaryBase64: binaryBase64,
+    extend: extend,
+    isArray: isArray,
+    isInArray: isInArray,
+    makeArray: makeArray,
+    each: each,
+    map: map,
+    filter: filter,
+    clone: clone,
+    attr: attr,
+    uuid: uuid,
+    camSafeUrlEncode: camSafeUrlEncode,
+    throttleOnProgress: throttleOnProgress,
+    getFileSize: getFileSize,
+    getSkewTime: getSkewTime,
+    error: error,
+    obj2str: obj2str,
+    getAuth: getAuth,
+    parseSelectPayload: parseSelectPayload,
+    getSourceParams: getSourceParams,
+    isBrowser: true,
+    isNode: isNode,
+    isCIHost: isCIHost,
+};
+
+module.exports = util;

+ 24 - 0
node_modules/cos-js-sdk-v5/test/index.html

@@ -0,0 +1,24 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>cos-js-sdk-v5-demo</title>
+    <link rel="stylesheet" href="./qunit-2.4.0.css">
+</head>
+<body>
+
+<h1 id="qunit-header">cos-js-sdk-v5</h1>
+<h2 id="qunit-banner"></h2>
+<ol id="qunit-tests"></ol>
+
+<script src = "//cdn.polyfill.io/v2/polyfill.min.js"></script>
+<script src="./qunit-2.4.0.js"></script>
+<script src="../dist/cos-js-sdk-v5.js"></script>
+<script src="../demo/common/cos-auth.min.js"></script>
+<script src="./test.js"></script>
+
+</body>
+</html>

+ 436 - 0
node_modules/cos-js-sdk-v5/test/qunit-2.4.0.css

@@ -0,0 +1,436 @@
+/*!
+ * QUnit 2.4.0
+ * https://qunitjs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2017-07-08T15:20Z
+ */
+
+/** Font Family and Sizes */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
+	font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
+}
+
+#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+	margin: 0;
+	padding: 0;
+}
+
+
+/** Header (excluding toolbar) */
+
+#qunit-header {
+	padding: 0.5em 0 0.5em 1em;
+
+	color: #8699A4;
+	background-color: #0D3349;
+
+	font-size: 1.5em;
+	line-height: 1em;
+	font-weight: 400;
+
+	border-radius: 5px 5px 0 0;
+}
+
+#qunit-header a {
+	text-decoration: none;
+	color: #C2CCD1;
+}
+
+#qunit-header a:hover,
+#qunit-header a:focus {
+	color: #FFF;
+}
+
+#qunit-banner {
+	height: 5px;
+}
+
+#qunit-filteredTest {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #366097;
+	background-color: #F4FF77;
+}
+
+#qunit-userAgent {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #FFF;
+	background-color: #2B81AF;
+	text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+
+/** Toolbar */
+
+#qunit-testrunner-toolbar {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #5E740B;
+	background-color: #EEE;
+}
+
+#qunit-testrunner-toolbar .clearfix {
+	height: 0;
+	clear: both;
+}
+
+#qunit-testrunner-toolbar label {
+	display: inline-block;
+}
+
+#qunit-testrunner-toolbar input[type=checkbox],
+#qunit-testrunner-toolbar input[type=radio] {
+	margin: 3px;
+	vertical-align: -2px;
+}
+
+#qunit-testrunner-toolbar input[type=text] {
+	box-sizing: border-box;
+	height: 1.6em;
+}
+
+.qunit-url-config,
+.qunit-filter,
+#qunit-modulefilter {
+	display: inline-block;
+	line-height: 2.1em;
+}
+
+.qunit-filter,
+#qunit-modulefilter {
+	float: right;
+	position: relative;
+	margin-left: 1em;
+}
+
+.qunit-url-config label {
+	margin-right: 0.5em;
+}
+
+#qunit-modulefilter-search {
+	box-sizing: border-box;
+	width: 400px;
+}
+
+#qunit-modulefilter-search-container:after {
+	position: absolute;
+	right: 0.3em;
+	content: "\25bc";
+	color: black;
+}
+
+#qunit-modulefilter-dropdown {
+	/* align with #qunit-modulefilter-search */
+	box-sizing: border-box;
+	width: 400px;
+	position: absolute;
+	right: 0;
+	top: 50%;
+	margin-top: 0.8em;
+
+	border: 1px solid #D3D3D3;
+	border-top: none;
+	border-radius: 0 0 .25em .25em;
+	color: #000;
+	background-color: #F5F5F5;
+	z-index: 99;
+}
+
+#qunit-modulefilter-dropdown a {
+	color: inherit;
+	text-decoration: none;
+}
+
+#qunit-modulefilter-dropdown .clickable.checked {
+	font-weight: bold;
+	color: #000;
+	background-color: #D2E0E6;
+}
+
+#qunit-modulefilter-dropdown .clickable:hover {
+	color: #FFF;
+	background-color: #0D3349;
+}
+
+#qunit-modulefilter-actions {
+	display: block;
+	overflow: auto;
+
+	/* align with #qunit-modulefilter-dropdown-list */
+	font: smaller/1.5em sans-serif;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > * {
+	box-sizing: border-box;
+	max-height: 2.8em;
+	display: block;
+	padding: 0.4em;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > button {
+	float: right;
+	font: inherit;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child {
+	/* insert padding to align with checkbox margins */
+	padding-left: 3px;
+}
+
+#qunit-modulefilter-dropdown-list {
+	max-height: 200px;
+	overflow-y: auto;
+	margin: 0;
+	border-top: 2px groove threedhighlight;
+	padding: 0.4em 0 0;
+	font: smaller/1.5em sans-serif;
+}
+
+#qunit-modulefilter-dropdown-list li {
+	white-space: nowrap;
+	overflow: hidden;
+	text-overflow: ellipsis;
+}
+
+#qunit-modulefilter-dropdown-list .clickable {
+	display: block;
+	padding-left: 0.15em;
+}
+
+
+/** Tests: Pass/Fail */
+
+#qunit-tests {
+	list-style-position: inside;
+}
+
+#qunit-tests li {
+	padding: 0.4em 1em 0.4em 1em;
+	border-bottom: 1px solid #FFF;
+	list-style-position: inside;
+}
+
+#qunit-tests > li {
+	display: none;
+}
+
+#qunit-tests li.running,
+#qunit-tests li.pass,
+#qunit-tests li.fail,
+#qunit-tests li.skipped,
+#qunit-tests li.aborted {
+	display: list-item;
+}
+
+#qunit-tests.hidepass {
+	position: relative;
+}
+
+#qunit-tests.hidepass li.running,
+#qunit-tests.hidepass li.pass:not(.todo) {
+	visibility: hidden;
+	position: absolute;
+	width:   0;
+	height:  0;
+	padding: 0;
+	border:  0;
+	margin:  0;
+}
+
+#qunit-tests li strong {
+	cursor: pointer;
+}
+
+#qunit-tests li.skipped strong {
+	cursor: default;
+}
+
+#qunit-tests li a {
+	padding: 0.5em;
+	color: #C2CCD1;
+	text-decoration: none;
+}
+
+#qunit-tests li p a {
+	padding: 0.25em;
+	color: #6B6464;
+}
+#qunit-tests li a:hover,
+#qunit-tests li a:focus {
+	color: #000;
+}
+
+#qunit-tests li .runtime {
+	float: right;
+	font-size: smaller;
+}
+
+.qunit-assert-list {
+	margin-top: 0.5em;
+	padding: 0.5em;
+
+	background-color: #FFF;
+
+	border-radius: 5px;
+}
+
+.qunit-source {
+	margin: 0.6em 0 0.3em;
+}
+
+.qunit-collapsed {
+	display: none;
+}
+
+#qunit-tests table {
+	border-collapse: collapse;
+	margin-top: 0.2em;
+}
+
+#qunit-tests th {
+	text-align: right;
+	vertical-align: top;
+	padding: 0 0.5em 0 0;
+}
+
+#qunit-tests td {
+	vertical-align: top;
+}
+
+#qunit-tests pre {
+	margin: 0;
+	white-space: pre-wrap;
+	word-wrap: break-word;
+}
+
+#qunit-tests del {
+	color: #374E0C;
+	background-color: #E0F2BE;
+	text-decoration: none;
+}
+
+#qunit-tests ins {
+	color: #500;
+	background-color: #FFCACA;
+	text-decoration: none;
+}
+
+/*** Test Counts */
+
+#qunit-tests b.counts                       { color: #000; }
+#qunit-tests b.passed                       { color: #5E740B; }
+#qunit-tests b.failed                       { color: #710909; }
+
+#qunit-tests li li {
+	padding: 5px;
+	background-color: #FFF;
+	border-bottom: none;
+	list-style-position: inside;
+}
+
+/*** Passing Styles */
+
+#qunit-tests li li.pass {
+	color: #3C510C;
+	background-color: #FFF;
+	border-left: 10px solid #C6E746;
+}
+
+#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
+#qunit-tests .pass .test-name               { color: #366097; }
+
+#qunit-tests .pass .test-actual,
+#qunit-tests .pass .test-expected           { color: #999; }
+
+#qunit-banner.qunit-pass                    { background-color: #C6E746; }
+
+/*** Failing Styles */
+
+#qunit-tests li li.fail {
+	color: #710909;
+	background-color: #FFF;
+	border-left: 10px solid #EE5757;
+	white-space: pre;
+}
+
+#qunit-tests > li:last-child {
+	border-radius: 0 0 5px 5px;
+}
+
+#qunit-tests .fail                          { color: #000; background-color: #EE5757; }
+#qunit-tests .fail .test-name,
+#qunit-tests .fail .module-name             { color: #000; }
+
+#qunit-tests .fail .test-actual             { color: #EE5757; }
+#qunit-tests .fail .test-expected           { color: #008000; }
+
+#qunit-banner.qunit-fail                    { background-color: #EE5757; }
+
+
+/*** Aborted tests */
+#qunit-tests .aborted { color: #000; background-color: orange; }
+/*** Skipped tests */
+
+#qunit-tests .skipped {
+	background-color: #EBECE9;
+}
+
+#qunit-tests .qunit-todo-label,
+#qunit-tests .qunit-skipped-label {
+	background-color: #F4FF77;
+	display: inline-block;
+	font-style: normal;
+	color: #366097;
+	line-height: 1.8em;
+	padding: 0 0.5em;
+	margin: -0.4em 0.4em -0.4em 0;
+}
+
+#qunit-tests .qunit-todo-label {
+	background-color: #EEE;
+}
+
+/** Result */
+
+#qunit-testresult {
+	color: #2B81AF;
+	background-color: #D2E0E6;
+
+	border-bottom: 1px solid #FFF;
+}
+#qunit-testresult .clearfix {
+	height: 0;
+	clear: both;
+}
+#qunit-testresult .module-name {
+	font-weight: 700;
+}
+#qunit-testresult-display {
+	padding: 0.5em 1em 0.5em 1em;
+	width: 85%;
+	float:left;
+}
+#qunit-testresult-controls {
+	padding: 0.5em 1em 0.5em 1em;
+  width: 10%;
+	float:left;
+}
+
+/** Fixture */
+
+#qunit-fixture {
+	position: absolute;
+	top: -10000px;
+	left: -10000px;
+	width: 1000px;
+	height: 1000px;
+}

Разница между файлами не показана из-за своего большого размера
+ 5048 - 0
node_modules/cos-js-sdk-v5/test/qunit-2.4.0.js


Разница между файлами не показана из-за своего большого размера
+ 3844 - 0
node_modules/cos-js-sdk-v5/test/test.js


+ 35 - 0
node_modules/cos-js-sdk-v5/test/watcher.js

@@ -0,0 +1,35 @@
+const pti = require('puppeteer-to-istanbul')
+const puppeteer = require('puppeteer');
+
+var fs = require('fs');
+var util = require('util');
+
+var logFile = fs.createWriteStream('log.txt', { flags: 'w' });
+  // Or 'w' to truncate the file every time the process starts.
+var logStdout = process.stdout;
+
+console.log = function () {
+  logFile.write(util.format.apply(null, arguments) + '\n');
+  logStdout.write(util.format.apply(null, arguments) + '\n');
+}
+console.error = console.log;
+
+(async () => {
+    const browser = await puppeteer.launch({args: ['--no-proxy-server', '--no-sandbox', '--disable-setuid-sandbox']});
+    const page = await browser.newPage();
+    page.on('console', async function (msg) {
+        var text = msg.text();
+        if (text.startsWith('[test-result]')) {
+            console.log('==[TESTING-ENDS]==')
+            const details = JSON.parse(text.replace('[test-result]', ''))
+            console.log(details)
+            const jsCoverage = await page.coverage.stopJSCoverage();
+            pti.write(jsCoverage, { includeHostname: true , storagePath: './.nyc_output' })
+            await browser.close()
+        } else {
+            console.log(msg.text())
+        }
+    });
+    await page.coverage.startJSCoverage();
+    await page.goto('http://127.0.0.1:3000/test');
+})()

+ 104 - 0
node_modules/cos-js-sdk-v5/webpack.config.js

@@ -0,0 +1,104 @@
+var fs = require('fs');
+var path = require('path');
+var webpack = require('webpack');
+var pkg = require('./package');
+
+// replaceVersion
+var replaceVersion = function () {
+    var filePath = path.resolve(__dirname, 'src/cos.js');
+    var content = fs.readFileSync(filePath).toString();
+    if (content) {
+        var newContent = content.replace(/(COS\.version) *= *['"]\d+\.\d+\.\d+['"];/, "$1 = '" + pkg.version + "';");
+        if (newContent !== content) {
+            fs.writeFileSync(filePath, newContent);
+            console.log('cos.js version updated.');
+        }
+    }
+};
+var replaceDevCode = function (list) {
+    list.forEach(function (fileName) {
+        var filePath = path.resolve(__dirname, fileName);
+        var content = fs.readFileSync(filePath).toString();
+        var newContent = content;
+        newContent = newContent.replace(/https:\/\/\w+\.com\/[\w\-]+\/server\//, 'https://example.com/');
+        newContent = newContent.replace(/test-125\d{7}/, 'test-1250000000');
+        newContent = newContent.replace(/'proxy' => 'http:\/\/[^']+',/, "'proxy' => '',");
+        newContent = newContent.replace(/proxy: 'http:\/\/[^']+',/, "proxy: '',");
+        newContent = newContent.replace(/AKID\w+/, 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
+        newContent = newContent.replace(/'secretKey' => '[^']+',/, "'secretKey' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',");
+        newContent = newContent.replace(/secretKey: '[^']+',/, "secretKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',");
+        newContent = newContent.replace(/'allowActions' *=> *array\([^)]+\)/, `'allowActions' => array(
+        // 所有 action 请看文档 https://cloud.tencent.com/document/product/436/31923
+        // 简单上传
+        'name/cos:PutObject',
+        // 分片上传
+        'name/cos:InitiateMultipartUpload',
+        'name/cos:ListMultipartUploads',
+        'name/cos:ListParts',
+        'name/cos:UploadPart',
+        'name/cos:CompleteMultipartUpload'
+    )`);
+        if (newContent !== content) {
+            console.log('replace ' + filePath);
+            fs.writeFileSync(filePath, newContent);
+        }
+    });
+};
+replaceVersion();
+
+module.exports = {
+    entry: path.resolve(__dirname, './index.js'),
+    output: {
+        path: path.resolve(__dirname, './dist'),
+        publicPath: '/dist/',
+        filename: 'cos-js-sdk-v5.js',
+        libraryTarget: 'umd',
+        library: 'COS',
+    },
+    module: {
+        rules: [
+            {
+                test: /\.js$/,
+                loader: 'babel-loader',
+                exclude: /node_modules/
+            }
+        ]
+    },
+    devServer: {
+        historyApiFallback: true,
+        noInfo: true
+    },
+    performance: {
+        hints: false
+    },
+};
+
+if (process.env.NODE_ENV === 'production') {
+    replaceDevCode([
+        'demo/demo.js',
+        'demo/queue/index.js',
+        'test/test.js',
+        'server/sts.js',
+        'server/sts.php',
+    ]);
+    module.exports.output.filename = 'cos-js-sdk-v5.min.js';
+    module.exports.plugins = (module.exports.plugins || []).concat([
+        new webpack.DefinePlugin({
+            'process.env': {
+                NODE_ENV: '"production"'
+            }
+        }),
+        new webpack.optimize.UglifyJsPlugin({
+            sourceMap: false,
+            output: {
+                ascii_only: true,
+            },
+            compress: {
+                warnings: false,
+            },
+        }),
+        new webpack.LoaderOptionsPlugin({
+            minimize: true
+        }),
+    ]);
+}

+ 73 - 0
node_modules/tim-js-sdk/README.md

@@ -0,0 +1,73 @@
+本文主要介绍如何快速地将腾讯云 IM SDK 集成到您的 Web 项目中,只要按照如下步骤进行配置,就可以完成 SDK 的集成工作。
+
+## 准备工作
+在集成 Web SDK 前,请确保您已完成以下步骤,请参见 [一分钟跑通 Demo](https://cloud.tencent.com/document/product/269/36838)。
+- 创建了腾讯云即时通信 IM 应用,并获取到 SDKAppID。
+- 获取密钥信息。
+
+## 集成 SDK
+您可以通过以下方式集成 SDK:
+
+### NPM 集成
+在您的项目中使用 npm 安装相应的 IM SDK 依赖。
+
+#### Web 项目:
+```javascript
+// IM Web SDK
+npm install tim-js-sdk --save
+// 发送图片、文件等消息需要的上传插件
+npm install tim-upload-plugin --save
+```
+
+在项目脚本里引入模块,并初始化。
+
+```javascript
+import TIM from 'tim-js-sdk';
+import TIMUploadPlugin from 'tim-upload-plugin';
+
+let options = {
+  SDKAppID: 0 // 接入时需要将 0 替换为您的云通信应用的 SDKAppID,类型为 Number
+};
+// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
+let tim = TIM.create(options); // SDK 实例通常用 tim 表示
+
+// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
+tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
+// tim.setLogLevel(1); // release级别,SDK 输出关键信息,生产环境时建议使用
+
+// 注册腾讯云即时通信 IM 上传插件
+tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});
+```
+
+### Script 集成
+在您的项目中使用 script 标签引入 SDK,并初始化。
+
+```html
+<!-- tim-js.js 和 tim-upload-plugin.js 可以从 https://github.com/tencentyun/TIMSDK/tree/master/H5/sdk 获取 -->
+<script src="./tim-js.js"></script>
+<script src="./tim-upload-plugin.js"></script>
+<script>
+var options = {
+  SDKAppID: 0 // 接入时需要将 0 替换为您的云通信应用的 SDKAppID
+};
+// 创建 SDK 实例,`TIM.create()`方法对于同一个 `SDKAppID` 只会返回同一份实例
+var tim = TIM.create(options);
+// 设置 SDK 日志输出级别,详细分级请参见 setLogLevel 接口的说明
+tim.setLogLevel(0); // 普通级别,日志量较多,接入时建议使用
+// tim.setLogLevel(1); // release级别,SDK 输出关键信息,生产环境时建议使用
+
+// 注册腾讯云即时通信 IM 上传插件
+tim.registerPlugin({'tim-upload-plugin': TIMUploadPlugin});
+
+// 接下来可以通过 tim 进行事件绑定和构建 IM 应用
+</script>
+```
+
+更详细的初始化流程请看 [SDK 初始化例子](https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html)
+
+#### 相关资源
+- [SDK 更新日志](https://cloud.tencent.com/document/product/269/38492)
+- [SDK 接口文档](https://web.sdk.qcloud.com/im/doc/zh-cn/SDK.html)
+- [常见问题](https://web.sdk.qcloud.com/im/doc/zh-cn/tutorial-01-faq.html)
+- [WebSocket 升级指引](https://web.sdk.qcloud.com/im/doc/zh-cn/tutorial-02-upgradeguideline.html)
+- [IM Web Demo](https://github.com/tencentyun/TIMSDK/tree/master/H5)

+ 51 - 0
node_modules/tim-js-sdk/package.json

@@ -0,0 +1,51 @@
+{
+  "_from": "tim-js-sdk",
+  "_id": "tim-js-sdk@2.15.0",
+  "_inBundle": false,
+  "_integrity": "sha512-WuqZ/gkdLiDT8zZLh95Lt7BjlXXOll7S3weF/+cJhKH8QAU/21m3jXfAxtMes6FRrWNDTUXI2HbRf4pVT6KAXA==",
+  "_location": "/tim-js-sdk",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "tag",
+    "registry": true,
+    "raw": "tim-js-sdk",
+    "name": "tim-js-sdk",
+    "escapedName": "tim-js-sdk",
+    "rawSpec": "",
+    "saveSpec": null,
+    "fetchSpec": "latest"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://repo.huaweicloud.com/repository/npm/tim-js-sdk/-/tim-js-sdk-2.15.0.tgz",
+  "_shasum": "ec620fcf4586fd8c7914c2fbb6a407ba8139578e",
+  "_spec": "tim-js-sdk",
+  "_where": "H:\\company-project\\instant_messaging",
+  "author": {
+    "name": "Tencent Cloud Terminal R&D Center"
+  },
+  "bugs": {
+    "url": "https://github.com/tencentyun/TIMSDK/issues"
+  },
+  "bundleDependencies": false,
+  "deprecated": false,
+  "description": "Tencent Cloud IM SDK for Web",
+  "homepage": "https://github.com/tencentyun/TIMSDK#readme",
+  "keywords": [
+    "即时通信",
+    "IM",
+    "腾讯云IM",
+    "即时通讯",
+    "通信"
+  ],
+  "license": "ISC",
+  "main": "tim-js.js",
+  "name": "tim-js-sdk",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/tencentyun/TIMSDK.git"
+  },
+  "version": "2.15.0"
+}

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/tim-js-sdk/tim-js-friendship.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/tim-js-sdk/tim-js.js


+ 94 - 0
node_modules/trtc-calling-js/README.md

@@ -0,0 +1,94 @@
+### 腾讯云实时音视频通话 TRTC CALLING SDK
+
+[TRTCCalling](https://www.npmjs.com/package/trtc-calling-js) 组件,是我们基于腾讯云 Web 版的 [TRTC SDK](https://trtc-1252463788.file.myqcloud.com/web/docs/TRTC.html) 和 [信令(TSignalling) SDK](https://webim-1252463788.cos.ap-shanghai.myqcloud.com/tsignaling/TSignaling.html) 组合而成的一个功能组件,用于支持双人和多人场景下的音视频通话通能。
+
+#### 接入方式
+> 从v0.6.0起,需要手动安装依赖 [trtc-js-sdk](https://www.npmjs.com/package/trtc-js-sdk) 和 [tim-js-sdk](https://www.npmjs.com/package/tim-js-sdk) 以及 [tsignaling](https://www.npmjs.com/package/tsignaling)
+>- 为了减小 trtc-calling-js.js 的体积,避免和接入侧已使用的 trtc-js-sdk 和 tim-js-sdk 以及 tsignaling 发生版本冲突,trtc-js-sdk 和 tim-js-sdk 以及 tsignaling 不再被打包到 trtc-calling-js.js,在使用前您需要手动安装依赖。
+```javascript
+  npm i trtc-js-sdk --save
+  npm i tim-js-sdk --save
+  npm i tsignaling --save
+  npm i trtc-calling-js --save
+ 
+  // 如果您通过 script 方式使用 trtc-calling-js,需要按顺序先手动引入 trtc.js
+  <script src="./trtc.js"></script>
+  
+  // 接着手动引入 tim-js.js
+  <script src="./tim-js.js"></script>
+  
+  // 然后再手动引入 tsignaling.js
+  <script src="./tsignaling.js"></script>
+
+  // 最后再手动引入 trtc-calling-js.js
+  <script src="./trtc-calling-js.js"></script>
+```
+
+
+
+### API list
+
+| API                               | 含义               |
+| :-------------------------------- | :----------------- |
+| new TRTCCalling(params)           | 初始化 SDK         |
+| setLogLevel(level)                | 设置日志级别       |
+| on(eventName, callback, context)  | 监听事件           |
+| off(eventName, callback, context) | 取消监听事件       |
+| login(params)                     | 登录               |
+| logout()                          | 登出               |
+| call(params)                      | 邀请通话           |
+| groupCall(params)                 | 邀请群通话         |
+| accept(params)                    | 接受通话邀请       |
+| reject(params)                    | 拒绝通话邀请       |
+| hangup()                          | 挂断               |
+| startRemoteView(params)           | 启动远端画面渲染   |
+| stopRemoteView(params)            | 停止远端画面渲染   |
+| startLocalView(params)            | 启动本地画面渲染   |
+| stopLocalView(params)             | 停止本地画面渲染   |
+| openCamera()                      | 启动摄像头         |
+| closeCamera()                     | 关闭摄像头         |
+| setMicMute(isMute)                | 设备麦克风是否静音 |
+| setVideoQuality(profile)          | 设置视频质量 |
+| switchToAudioCall()               | 视频通话切换语音通话 |
+| switchToVideoCall()               | 语音通话切换视频通话 |
+| getCameras()                      | 获取摄像头设备列表 |
+| getMicrophones()                  | 获取麦克风设备列表 |
+| switchDevice()                    | 切换摄像头或麦克风设备 |
+
+
+
+### event list
+| event                                            | 含义                      |
+| :----------------------------------------------- | :------------------------ |
+| TRTCCalling.EVENT.INVITED,                       | 收到邀请通知              |
+| TRTCCalling.EVENT.REJECT,                        | 被邀用户拒绝通话          |
+| TRTCCalling.EVENT.NO_RESP,                       | 被邀用户超时无应答        |
+| TRTCCalling.EVENT.LINE_BUSY,                     | 被邀用户正在通话中,忙线  |
+| TRTCCalling.EVENT.CALLING_CANCEL,                | 本次通话被取消了          |
+| TRTCCalling.EVENT.CALLING_TIMEOUT,               | 本次通话超时未应答        |
+| TRTCCalling.EVENT.CALLING_END,                   | 本次通话结束              |
+| TRTCCalling.EVENT.USER_ENTER,                    | 用户进入通话              |
+| TRTCCalling.EVENT.USER_LEAVE,                    | 用户离开通话              |
+| TRTCCalling.EVENT.KICKED_OUT,                    | 重复登录,被踢出          |
+| TRTCCalling.EVENT.USER_VIDEO_AVAILABLE,          | 远端用户开启/关闭了摄像头 |
+| TRTCCalling.EVENT.USER_AUDIO_AVAILABLE,          | 远端用户开启/关闭了麦克风 |
+| TRTCCalling.EVENT.SDK_READY,                     | SDK 进入 ready 状态 |
+| TRTCCalling.EVENT.SDK_NOT_READY,                 | SDK 没有 ready 状态 |
+| TRTCCalling.EVENT.GROUP_CALL_INVITEE_LIST_UPDATE | 群聊更新邀请列表 |
+
+### Error code
+| code               | 错误类型           | 含义                             |
+| :----------------- | :---------------- | :------------------------------ |
+| 60001              | 方法调用失败        | switchToAudioCall 调用失败        |
+| 60002              | 方法调用失败        | switchToVideoCall 调用失败        |
+| 60003              | 权限获取失败        | 没有可用的麦克风设备                |
+| 60004              | 权限获取失败        | 没有可用的摄像头设备                |
+| 60005              | 权限获取失败        | 用户禁止使用设备                   |
+
+
+### 参考文档
+- [腾讯实时音视频 TRTC](https://cloud.tencent.com/document/product/647/16788)
+- [腾讯云即时通信 IM](https://cloud.tencent.com/document/product/269/1498)
+- [TSignaling API](https://web.sdk.qcloud.com/component/tsignaling/doc/zh-cn/TSignaling.html)
+- [TRTCCalling API](https://web.sdk.qcloud.com/component/trtccalling/doc/web/zh-cn/TRTCCalling.html)
+

+ 45 - 0
node_modules/trtc-calling-js/package.json

@@ -0,0 +1,45 @@
+{
+  "_from": "trtc-calling-js",
+  "_id": "trtc-calling-js@1.0.1",
+  "_inBundle": false,
+  "_integrity": "sha512-q8jnkfRWvDf9wSOXk+fayyJOvMYHSf9pIbYB4v0QDH1WdPK71gezJnQevPTBxncI7xrxG+tpIOyBRLV5Jigqlg==",
+  "_location": "/trtc-calling-js",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "tag",
+    "registry": true,
+    "raw": "trtc-calling-js",
+    "name": "trtc-calling-js",
+    "escapedName": "trtc-calling-js",
+    "rawSpec": "",
+    "saveSpec": null,
+    "fetchSpec": "latest"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://repo.huaweicloud.com/repository/npm/trtc-calling-js/-/trtc-calling-js-1.0.1.tgz",
+  "_shasum": "2576685904468cc806e7389c2b590df9867ec1e7",
+  "_spec": "trtc-calling-js",
+  "_where": "H:\\company-project\\instant_messaging",
+  "author": {
+    "name": "Tencent Cloud Terminal R&D Center"
+  },
+  "bundleDependencies": false,
+  "deprecated": false,
+  "description": "腾讯云 TRTC CALLING SDK",
+  "keywords": [
+    "视频语音通话",
+    "腾讯云实时音视频 TRTC",
+    "WebRTC"
+  ],
+  "license": "ISC",
+  "main": "trtc-calling-js.js",
+  "name": "trtc-calling-js",
+  "repository": {
+    "type": "git",
+    "url": "git@git.code.oa.com:TRDCWeb/trtc-calling-webrtc.git"
+  },
+  "version": "1.0.1"
+}

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/trtc-calling-js/trtc-calling-js.js


Разница между файлами не показана из-за своего большого размера
+ 84 - 0
node_modules/trtc-js-sdk/README.md


+ 51 - 0
node_modules/trtc-js-sdk/package.json

@@ -0,0 +1,51 @@
+{
+  "_from": "trtc-js-sdk",
+  "_id": "trtc-js-sdk@4.11.8",
+  "_inBundle": false,
+  "_integrity": "sha512-y5QOnLoAd2pDVpMBTx1HVCISsg912ajJUfnbxaLYAllwv9i2paIaJKVzwnE3IPbGM8XaNZVTYUOlO4vUpr+R8Q==",
+  "_location": "/trtc-js-sdk",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "tag",
+    "registry": true,
+    "raw": "trtc-js-sdk",
+    "name": "trtc-js-sdk",
+    "escapedName": "trtc-js-sdk",
+    "rawSpec": "",
+    "saveSpec": null,
+    "fetchSpec": "latest"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://repo.huaweicloud.com/repository/npm/trtc-js-sdk/-/trtc-js-sdk-4.11.8.tgz",
+  "_shasum": "340ed6c0e1a3d650a42af758dffb3713988979b3",
+  "_spec": "trtc-js-sdk",
+  "_where": "H:\\company-project\\instant_messaging",
+  "author": {
+    "name": "Tencent Cloud Client R&D Center"
+  },
+  "bugs": {
+    "url": "https://github.com/tencentyun/TRTCSDK/issues"
+  },
+  "bundleDependencies": false,
+  "deprecated": false,
+  "description": "Tencent Cloud RTC SDK for Web",
+  "homepage": "https://github.com/tencentyun/TRTCSDK#readme",
+  "keywords": [
+    "实时音视频",
+    "视频通话",
+    "音频通话",
+    "WEBRTC",
+    "直播"
+  ],
+  "license": "ISC",
+  "main": "trtc.js",
+  "name": "trtc-js-sdk",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/tencentyun/TRTCSDK.git"
+  },
+  "version": "4.11.8"
+}

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/trtc-js-sdk/trtc.esm.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/trtc-js-sdk/trtc.js


Разница между файлами не показана из-за своего большого размера
+ 1 - 0
node_modules/trtc-js-sdk/trtc.umd.js


+ 62 - 0
node_modules/tsignaling/README.md

@@ -0,0 +1,62 @@
+### 简介
+
+腾讯云 Web 信令 SDK,以腾讯云即时通信 IM 为基础,在实时音视频场景用于发送和接收信令消息,如发起单人、多人通话等。接入前,您需要在 [云通信控制台](https://console.cloud.tencent.com/avc) 中创建一个云通信应用,并取得 SDKAppID,并了解腾讯云实时音视频 [TRTC](https://cloud.tencent.com/product/trtc/developer)。
+
+### api list
+
+| api | 含义 |
+| :--- | :--- |
+| new TSignaling(options) | 初始化信令 SDK |
+| setLogLevel(level) | 设置日志级别 |
+| on(eventName, handler, context) | 监听事件 |
+| login(options) | 登录 |
+| logout() | 登出 |
+| joinGroup(groupID) | 加群 |
+| quitGroup(groupID) | 退群 |
+| sendTextMessage(options) | 发送文本消息 |
+| sendCustomMessage(options) | 发送自定义消息 |
+| invite(options) | 邀请单个人 |
+| inviteInGroup(options) | 群内邀请某些人 |
+| cancel(options) | 邀请发起者取消邀请 |
+| accept(options) | 被邀请人接受邀请 |
+| reject(options) | 被邀请人拒绝邀请 |
+
+### event list
+| event | 含义 |
+| :--- | :--- |
+| TSignaling.EVENT.NEW_INVITATION_RECEIVED | 收到新的邀请 |
+| TSignaling.EVENT.INVITEE_ACCEPTED | 被邀请人接受了邀请 |
+| TSignaling.EVENT.INVITEE_REJECTED | 被邀请人拒绝了邀请 |
+| TSignaling.EVENT.INVITATION_CANCELLED | 邀请被发起者取消 |
+| TSignaling.EVENT.INVITATION_TIMEOUT | 邀请超时 |
+| TSignaling.EVENT.SDK_READY | sdk ready,可以发信令消息 |
+| TSignaling.EVENT.SDK_NOT_READY | sdk not ready,不可以发信令消息 |
+| TSignaling.EVENT.TEXT_MESSAGE_RECEIVED | 收到普通文本消息 |
+| TSignaling.EVENT.CUSTOM_MESSAGE_RECEIVED | 收到普通自定义消息 |
+| TSignaling.EVENT.REMOTE_USER_JOIN | 有远端用户加入群 |
+| TSignaling.EVENT.REMOTE_USER_LEAVE | 有远端用户离开群
+| TSignaling.EVENT.KICKED_OUT | 被腾讯云即时通信 IM 系统踢下线 |
+| TSignaling.EVENT.NET_STATE_CHANGE | 用户网络发生变化 |
+
+### type list
+
+| type | 含义 |
+| :-----| :----- |
+| TSignaling.TYPES.MSG_PRIORITY_HIGH | 群消息高优先级。建议选择该优先级的消息类型:红包消息和礼物消息 |
+| TSignaling.TYPES.TYPES.MSG_PRIORITY_NORMAL | 群消息普通优先级。建议选择该优先级的消息类型:普通文本消息 |
+| TSignaling.TYPES.MSG_PRIORITY_LOW | 群消息低优先级。建议选择该优先级的消息类型:点赞消息 |
+| TSignaling.TYPES.MSG_PRIORITY_LOWEST | 群消息最低优先级。建议选择该优先级的消息类型:最不重要的消息 |
+| TSignaling.TYPES.KICKED_OUT_MULT_ACCOUNT | Web 端实例同时在线个数超限被踢 |
+| TSignaling.TYPES.KICKED_OUT_MULT_DEVICE | 多端登录超限被踢 |
+| TSignaling.TYPES.KICKED_OUT_USERSIG_EXPIRED | userSig 过期被踢 |
+| TSignaling.TYPES.NET_STATE_CONNECTED | 已接入网络 |
+| TSignaling.TYPES.NET_STATE_CONNECTING | 连接中 |
+| TSignaling.TYPES.NET_STATE_DISCONNECTED | 未接入网络 |
+| TSignaling.TYPES.ENTER_ROOM_SUCCESS | 加入群成功 |
+| TSignaling.TYPES.ALREADY_IN_ROOM | 已在群内 |
+
+### 参考文档
+
+- [腾讯云即时通信 IM](https://cloud.tencent.com/document/product/269/1498)
+- [WebIM API](https://imsdk-1252463788.file.myqcloud.com/IM_DOC/Web/TIM.html)
+- [腾讯实时音视频 TRTC](https://cloud.tencent.com/document/product/647/16788)

+ 51 - 0
node_modules/tsignaling/package.json

@@ -0,0 +1,51 @@
+{
+  "_from": "tsignaling",
+  "_id": "tsignaling@0.8.0",
+  "_inBundle": false,
+  "_integrity": "sha512-BtqX2YKa4pyMT4efLoIJQ6Xrc+6chxSuNnVtEpGLRjQOqkG5casA/oj8qMLRzXl0/0VQoPJ5YTJCzuU5SPjpVw==",
+  "_location": "/tsignaling",
+  "_phantomChildren": {},
+  "_requested": {
+    "type": "tag",
+    "registry": true,
+    "raw": "tsignaling",
+    "name": "tsignaling",
+    "escapedName": "tsignaling",
+    "rawSpec": "",
+    "saveSpec": null,
+    "fetchSpec": "latest"
+  },
+  "_requiredBy": [
+    "#USER",
+    "/"
+  ],
+  "_resolved": "https://repo.huaweicloud.com/repository/npm/tsignaling/-/tsignaling-0.8.0.tgz",
+  "_shasum": "670d4f3a3ad17541da897275893257a9e7b873d5",
+  "_spec": "tsignaling",
+  "_where": "H:\\company-project\\instant_messaging",
+  "author": {
+    "name": "Tencent Cloud Terminal R&D Center"
+  },
+  "bugs": {
+    "url": "https://github.com/tencentyun/TIMSDK/issues"
+  },
+  "bundleDependencies": false,
+  "deprecated": false,
+  "description": "腾讯云 Web 信令 SDK",
+  "homepage": "https://github.com/tencentyun/TIMSDK#readme",
+  "keywords": [
+    "信令",
+    "腾讯云即时通信 IM",
+    "腾讯云实时音视频 TRTC",
+    "WebRTC",
+    "Electron"
+  ],
+  "license": "ISC",
+  "main": "tsignaling-js.js",
+  "name": "tsignaling",
+  "repository": {
+    "type": "git",
+    "url": "git+ssh://git@github.com/tencentyun/TIMSDK.git"
+  },
+  "version": "0.8.0"
+}

Разница между файлами не показана из-за своего большого размера
+ 10 - 0
node_modules/tsignaling/tsignaling-js.js


Разница между файлами не показана из-за своего большого размера
+ 10 - 0
node_modules/tsignaling/tsignaling-wx.js


+ 22 - 0
node_modules/xmldom/.travis.yml

@@ -0,0 +1,22 @@
+language: node_js
+
+node_js:
+  - '0.10'
+
+branches:
+  only:
+    - master
+    - proof
+    - travis-ci
+
+# Not using `npm install --dev` because it is recursive. It will pull in the all
+# development dependencies for CoffeeScript. Way too much spew in the Travis CI
+# build output.
+
+before_install:
+  - npm install
+  - npm install istanbul coveralls
+
+env:
+  global:
+  - secure: "BxUHTsa1WVANLQoimilbZwa1MCWSdM9hOmPWBE/rsYb7uT/iiqkRXXwnWhKtN5CLvTvIQbiAzq4iyPID0S8UHrnxClYQrOuA6QkrtwgIEuDAmijao/bgxobPOremvkwXcpMGIwzYKyYQQtSEaEIQbqf6gSSKW9dBh/GZ/vfTsqo="

+ 8 - 0
node_modules/xmldom/LICENSE

@@ -0,0 +1,8 @@
+You can choose any one of those:
+
+The MIT License (MIT):
+
+link:http://opensource.org/licenses/MIT
+
+LGPL:
+http://www.gnu.org/licenses/lgpl.html

+ 0 - 0
node_modules/xmldom/__package__.js


Некоторые файлы не были показаны из-за большого количества измененных файлов