@smart100/spu-web-plugin 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,129 @@
1
+ interface IMultiUploadOptions {
2
+ bucket: string
3
+ key: string
4
+ partSize?: number
5
+ parallel: number
6
+ onProgress?: (number: number) => void
7
+ }
8
+ interface IUploadPartRes {
9
+ PartNumber: number
10
+ ETag: string
11
+ }
12
+
13
+ interface ITask<T> {
14
+ (): Promise<T>
15
+ }
16
+
17
+ export const obsMultiUpload = async (obs: any, file: File | Blob, options: IMultiUploadOptions) => {
18
+ const partSize = options.partSize || 1024 * 1024 // 1M
19
+ const parallel = options.parallel || 3
20
+ const initialRes = await obs.initiateMultipartUpload({
21
+ Bucket: options.bucket,
22
+ Key: options.key
23
+ })
24
+ if (initialRes.CommonMsg.Status < 300) {
25
+ const { UploadId } = initialRes.InterfaceResult
26
+ const count = Math.ceil(file.size / partSize)
27
+ // const dones: Array<IUploadPartRes> = []
28
+ const tasks: Array<ITask<IUploadPartRes>> = []
29
+ const transferredArr = new Array(count).fill(0)
30
+ for (let i = 1; i <= count; i++) {
31
+ const uploadPart = async () => {
32
+ const partRes = await obs.uploadPart({
33
+ Bucket: options.bucket,
34
+ Key: options.key,
35
+ // 设置分段号,范围是1~10000
36
+ PartNumber: i,
37
+ // 设置Upload ID
38
+ UploadId: UploadId,
39
+ // 设置将要上传的大文件
40
+ SourceFile: file, // 设置分段大小
41
+ PartSize: partSize,
42
+ // 设置分段的起始偏移大小
43
+ Offset: partSize * (i - 1),
44
+ ProgressCallback: (transferredAmount: number, totalAmount: number) => {
45
+ // TODO 不能直接加,transferredAmount有重复的
46
+ transferredArr[i - 1] = transferredAmount
47
+ const transferred = transferredArr.reduce((item, prev) => {
48
+ return item + prev
49
+ }, 0)
50
+ let percent = transferred / file.size
51
+ if (percent === 1) {
52
+ percent = 0.9999999
53
+ }
54
+ options.onProgress && options.onProgress(percent)
55
+ }
56
+ })
57
+ if (partRes.CommonMsg.Status < 300) {
58
+ // dones.push({
59
+ // part: i,
60
+ // etag: partRes.InterfaceResult.ETag
61
+ // })
62
+ return {
63
+ PartNumber: i,
64
+ ETag: partRes.InterfaceResult.ETag
65
+ }
66
+ } else {
67
+ throw partRes.CommonMsg.Message
68
+ }
69
+ }
70
+ tasks.push(uploadPart)
71
+ }
72
+ const partsRes = await executeTasks(tasks, parallel)
73
+ // complete
74
+ const completeRes = await obs.completeMultipartUpload({
75
+ Bucket: options.bucket,
76
+ Key: options.key,
77
+ UploadId: UploadId,
78
+ Parts: partsRes
79
+ })
80
+ if (completeRes.CommonMsg.Status < 300) {
81
+ // 进度条
82
+ options.onProgress && options.onProgress(1)
83
+ return true
84
+ } else {
85
+ throw completeRes.CommonMsg.Message
86
+ }
87
+ } else {
88
+ console.error(initialRes)
89
+ throw initialRes.CommonMsg.Message
90
+ }
91
+ }
92
+
93
+ const executeTasks = async <T>(tasks: Array<ITask<T>>, parallel = 3): Promise<Array<T>> => {
94
+ return new Promise((resolve, reject) => {
95
+ const todos = tasks.slice(0, parallel)
96
+ const pendings = tasks.slice(parallel)
97
+ let success = 0
98
+ const res: Array<T> = []
99
+ const dealPending = (todoRes: any, index?: number): Promise<any> | undefined => {
100
+ success = success + 1
101
+ if (index !== undefined && index !== null) {
102
+ res[index] = todoRes
103
+ }
104
+ if (success === tasks.length) {
105
+ resolve(res)
106
+ }
107
+ if (!pendings.length) return
108
+ const todo = pendings.shift()
109
+ const todoIndex = tasks.findIndex((task) => {
110
+ return task === todo
111
+ })
112
+ return todo && todo()
113
+ .then((todoRes) => dealPending(todoRes, todoIndex))
114
+ .catch(reject)
115
+ }
116
+ if (!pendings.length) {
117
+ const running = todos.map((todo) => {
118
+ return todo()
119
+ })
120
+ return Promise.all(running).then(resolve).catch(reject)
121
+ }
122
+ for (let i = 0; i < todos.length; i++) {
123
+ const todo = todos[i]
124
+ todo()
125
+ .then((todoRes) => dealPending(todoRes, i))
126
+ .catch(reject)
127
+ }
128
+ })
129
+ }
@@ -0,0 +1,131 @@
1
+ // import { noBaseRequest } from '@/service/http'
2
+ import { apaasAxios } from '../axios'
3
+
4
+ export type ServToken = {
5
+ accesskeyid: string
6
+ accesskeysecret: string
7
+ expiration: string
8
+ securitytoken: string
9
+ }
10
+
11
+ export type Response<T> = {
12
+ // eslint-disable-next-line camelcase
13
+ resp_data: T
14
+ }
15
+
16
+ // 一个小时的超时能力 1000 * 60 * 60
17
+ let last = 0
18
+ let servtoken: ServToken | null = null
19
+ let isGetting = false
20
+ let xhr: Promise<ServToken> | null = null
21
+
22
+ const getServToken = async () => {
23
+ try {
24
+ const response: ServToken = await apaasAxios.get('/api/teapi/auth/servtoken', {}).then((res: any) => res.data)
25
+ // debugger
26
+ return response
27
+ } catch (e) {
28
+ throw new Error((e as any).errorMsg || 'get servtoken error')
29
+ }
30
+ }
31
+
32
+ export const initServToken = () => {
33
+ return new Promise<ServToken>((resolve, reject) => {
34
+ // 在请求中,排队列
35
+ if (isGetting && xhr) {
36
+ xhr
37
+ .then((res) => {
38
+ if (res) {
39
+ servtoken = res
40
+ last = new Date(res.expiration).getTime()
41
+ isGetting = false
42
+ xhr = null
43
+ resolve(servtoken)
44
+ } else {
45
+ // eslint-disable-next-line prefer-promise-reject-errors
46
+ reject(null)
47
+ }
48
+ // return res
49
+ })
50
+ .catch(() => {
51
+ xhr = null
52
+ isGetting = false
53
+ // return null
54
+ // eslint-disable-next-line prefer-promise-reject-errors
55
+ reject(null)
56
+ })
57
+ } else {
58
+ if (!last || last - Date.now() < 1000 * 60 * 5) {
59
+ // 过期了 重新请求
60
+ isGetting = true
61
+ xhr = getServToken()
62
+ xhr
63
+ .then((res) => {
64
+ servtoken = res
65
+ last = new Date(res.expiration).getTime()
66
+ isGetting = false
67
+ xhr = null
68
+ // return res
69
+ resolve(servtoken)
70
+ })
71
+ .catch(() => {
72
+ xhr = null
73
+ isGetting = false
74
+ // return null
75
+ // eslint-disable-next-line prefer-promise-reject-errors
76
+ reject(null)
77
+ })
78
+ } else {
79
+ // 没过期
80
+ resolve(servtoken as ServToken)
81
+ }
82
+ }
83
+ })
84
+ }
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+ // // let last = 0
95
+ // // let servtoken
96
+ // let isRequesting = false
97
+ // const getServToken = function () {
98
+ // let servtoken = wx.getStorageSync('servtoken')
99
+ // let last
100
+ // if (servtoken) {
101
+ // last = new Date(servtoken.expiration).getTime()
102
+ // }
103
+ // const now = Date.now()
104
+ // if (!servtoken || (last - now < (1000 * 60 * 5))) {
105
+ // wx.removeStorageSync('servtoken')
106
+ // if (!isRequesting) {
107
+ // isRequesting = true
108
+ // return request({
109
+ // url: `${api.HOST}/api/teapi/auth/servtoken`,
110
+ // method: 'get',
111
+ // isShowLoading: false
112
+ // }).then((res) => {
113
+ // wx.setStorageSync('servtoken', res.data.resp_data)
114
+ // isRequesting = false
115
+ // return res.data.resp_data
116
+ // })
117
+ // } else {
118
+ // return new Promise((resolve, reject) => {
119
+ // const fn = setInterval(() => {
120
+ // let servtoken = wx.getStorageSync('servtoken')
121
+ // if (servtoken) {
122
+ // resolve(servtoken)
123
+ // clearInterval(fn)
124
+ // }
125
+ // }, 200)
126
+ // })
127
+ // }
128
+ // } else {
129
+ // return Promise.resolve(servtoken)
130
+ // }
131
+ // }
@@ -0,0 +1,145 @@
1
+ import CloudServ from '../cloudServ'
2
+ import { initServToken } from './servtoken'
3
+ import { v4 as uuidv4 } from 'uuid'
4
+ import OSS from '../package/ali-oss/aliyun-oss-sdk.apaas.min.js'
5
+ // const OSS = require('../package/ali-oss/aliyun-oss-sdk.apaas.min.js')
6
+ import ObsClient from '../package/huaweicloud-obs/esdk-obs-browserjs.3.22.3.min.js'
7
+ // const ObsClient = require('../package/huaweicloud-obs/esdk-obs-browserjs.3.22.3.min.js')
8
+ import dayjs from 'dayjs'
9
+ import co from 'co'
10
+ import login from '../login'
11
+ import { obsMultiUpload } from './multiUpload'
12
+
13
+
14
+
15
+ interface IUpload {
16
+ type?: 'att' | 'img',
17
+ file: File,
18
+ source?: string,
19
+ datetime?: string | number,
20
+ storagetype?: StorageType,
21
+ onprogress?: (p: number, _checkpoint?: IAny) => void
22
+ }
23
+
24
+ const upload = async ({
25
+ type = 'img',
26
+ file,
27
+ source = '',
28
+ datetime = '',
29
+ storagetype = 'storage',
30
+ onprogress,
31
+ }: IUpload) => {
32
+ if (!file) throw Error('请传入文件')
33
+ const cloudServStorage = CloudServ.get(storagetype)
34
+ if (!cloudServStorage) throw Error('无可用存储设置')
35
+ const servToken = await initServToken()
36
+ if (!servToken) throw Error('无可用servToken')
37
+
38
+ const isAliYun = CloudServ.isAliyun(storagetype)
39
+ const isHuawei = CloudServ.isHuawei(storagetype)
40
+ const tenantCode = login.getUser('tenantcode')
41
+ const suffix = '.' + file.name.substring(file.name.lastIndexOf('.') + 1)
42
+ source = source ? source : (uuidv4() + suffix)
43
+ datetime = datetime ? datetime : Date.now()
44
+ const date = dayjs(+datetime).format('YYYYMMDD')
45
+ const objectKey = `${source.slice(0, 3)}/${type}/${date}/${tenantCode}/${source}`
46
+
47
+ // console.log(file)
48
+ // console.log(source)
49
+ // console.log(datetime)
50
+ const promise = new Promise(async (resolve, reject) => {
51
+ if (isAliYun) {
52
+ const ossClient = new OSS({
53
+ // region: cloudServ.cloudserv_storage_storageendpoint,
54
+ endpoint: cloudServStorage.cloudserv_storage_storageendpoint,
55
+ accessKeyId: servToken.accesskeyid,
56
+ accessKeySecret: servToken.accesskeysecret,
57
+ stsToken: servToken.securitytoken,
58
+ bucket: cloudServStorage.cloudserv_storage_storagebucket,
59
+ secure: true
60
+ })
61
+ // promise.cancel = () => {
62
+ // ossClient.cancel()
63
+ // reject(new Error('Cancel'))
64
+ // }
65
+ co(function* () {
66
+ yield ossClient.multipartUpload(objectKey, file, {
67
+ headers: {
68
+ 'Content-Disposition': 'filename="' + (file.name && encodeURIComponent(file.name)) // 阿里云提供的下载名字
69
+ },
70
+ progress: function* (p: number, _checkpoint: IAny): any {
71
+ // console.log('httpUploadProgress', p)
72
+ onprogress && onprogress(p, _checkpoint)
73
+ if (p === 1) {
74
+ resolve({
75
+ source,
76
+ filename: file.name,
77
+ type: file.type,
78
+ date: date,
79
+ datetime: datetime,
80
+ file
81
+ })
82
+ }
83
+ }
84
+ })
85
+ }).catch((error: any) => {
86
+ console.error(error)
87
+ reject(error)
88
+ })
89
+ } else if (isHuawei) {
90
+ const obs = new ObsClient({
91
+ access_key_id: servToken.accesskeyid,
92
+ secret_access_key: servToken.accesskeysecret,
93
+ server: cloudServStorage.cloudserv_storage_storageendpoint,
94
+ security_token: servToken.securitytoken
95
+ })
96
+ // const obs = new ObsClient({
97
+ // access_key_id: '75ISL4GWAOOO1USWUMRG',
98
+ // secret_access_key: 'srn6eJ1BpFbjxoFrJgiQjeS65Z3eKC3rnqeyBBlL',
99
+ // server: cloudServ.cloudserv_storage_storageendpoint,
100
+ // security_token: 'gQ5jbi1zb3V0aHdlc3QtMogAsKjYcI5CQldRAvQQJysdkZ7tAt6arLsoWHFGCaco8s8FPk6wtbslHWhvg2SZh3QMM4aUA4FhPEWQt9A7gXoC_Lh4DpF6hhHIxUyACKgakNHNPdPegy5G9-sibBXkGueIY1X3K12tzpjbyd08esLKEEu-M_QmfDoDdkgOcyidITc-lOg5EzXb27f91Ym26u2mAMTaNjCLRulJ4rziLSW6IAprSx8LUkuQQE-wUz-tMzVL9oFiVykHz980o0Y0CNdCIwn98Y-xbMdslZ3U8raydy6Wnf2LchXc0ajvMix0gg-CV0tpA4cgiZFqPxwEDXSv42hvfccboWlpGmOVR3llHLUirrlgFod8rhm-Rmk6MIfQw4NA8rddow1Gx6g-MugFV5arMDLfsOhqeSFQRJWizb3q50zk6GcUFulewitxP8HSkXMGt_rDDYCcCEmdu15D3imX5431Mbdt0qCgxH80OPCDmFXw0xMOsggxE0PBVexVY2x3wHGeql3JNyevUZAhqlskNNu77ui2Vnp-ZbHMcxgDLcPuAULINId4V_QGdhAkDaxQk53AE237DAFXtlyWWaBRMsTNVnpq9mCXJup9pdBbjLRVAO4OxfYVnwwvl-w_mb-xCgOf5EPHqA_zbZF8z-ad6JjWgLOQCHaawE7kNGHIQwAgzneik33wP2jPlG1ak9KEWyXr1n2QMJCmDM3bIrRit5_8LLFoPjXcwurBjZ-AomM_ztOe34sdr357atlQcPD7a2xWtrvn9mnqqndg12m7QxnwkmJsOYK4ZO5Hoyb2vd_NX2Nd9PaSIVAcFw=='
101
+ // })
102
+ try {
103
+ const uploadRes = await obsMultiUpload(obs, file, {
104
+ bucket: cloudServStorage.cloudserv_storage_storagebucket,
105
+ key: objectKey,
106
+ parallel: 3,
107
+ onProgress: (percent: number) => {
108
+ onprogress && onprogress(percent)
109
+ }
110
+ })
111
+ if (uploadRes) {
112
+ resolve({
113
+ source,
114
+ filename: file.name,
115
+ type: file.type,
116
+ date: date,
117
+ datetime: datetime,
118
+ file
119
+ })
120
+ }
121
+ } catch (e) {
122
+ console.error(e)
123
+ reject(e)
124
+ }
125
+ // obs.putObject({
126
+ // Bucket: cloudServ.cloudserv_storage_storagebucket,
127
+ // Key: objectKey,
128
+ // SourceFile: file
129
+ // }, (err, result) => {
130
+ // result.CommonMsg.Status
131
+ // console.error(err)
132
+ // console.log(result)
133
+ // debugger
134
+ // })
135
+ } else {
136
+ throw Error('暂不支持非阿里云OSS/华为云OBS存储类型')
137
+ }
138
+ })
139
+
140
+ return promise
141
+ }
142
+
143
+ export default {
144
+ upload
145
+ }