@cloudbase/storage 2.23.4-alpha.0 → 2.24.0
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.
- package/dist/cjs/index.js +51 -712
- package/dist/cjs/storage.d.ts +53 -0
- package/dist/cjs/storage.js +718 -0
- package/dist/cjs/supabase/errors.d.ts +20 -0
- package/dist/cjs/supabase/errors.js +65 -0
- package/dist/cjs/supabase/index.d.ts +141 -0
- package/dist/cjs/supabase/index.js +689 -0
- package/dist/cjs/supabase/types.d.ts +64 -0
- package/dist/cjs/supabase/types.js +3 -0
- package/dist/esm/index.js +51 -712
- package/dist/esm/storage.d.ts +53 -0
- package/dist/esm/storage.js +715 -0
- package/dist/esm/supabase/errors.d.ts +20 -0
- package/dist/esm/supabase/errors.js +61 -0
- package/dist/esm/supabase/index.d.ts +141 -0
- package/dist/esm/supabase/index.js +686 -0
- package/dist/esm/supabase/types.d.ts +64 -0
- package/dist/esm/supabase/types.js +2 -0
- package/package.json +4 -4
- package/src/index.ts +56 -650
- package/src/storage.ts +698 -0
- package/src/supabase/errors.ts +43 -0
- package/src/supabase/index.ts +730 -0
- package/src/supabase/types.ts +132 -0
package/src/storage.ts
ADDED
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
import { constants, utils, helpers } from '@cloudbase/utilities'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ICloudbaseFileMetaDataRes,
|
|
5
|
+
ICloudbaseFileInfo,
|
|
6
|
+
ICloudbaseUploadFileParams,
|
|
7
|
+
ICloudbaseUploadFileResult,
|
|
8
|
+
ICloudbaseGetUploadMetadataParams,
|
|
9
|
+
ICloudbaseDeleteFileParams,
|
|
10
|
+
ICloudbaseDeleteFileResult,
|
|
11
|
+
ICloudbaseGetTempFileURLResult,
|
|
12
|
+
ICloudbaseGetTempFileURLParams,
|
|
13
|
+
ICloudbaseDownloadFileResult,
|
|
14
|
+
ICloudbaseDownloadFileParams,
|
|
15
|
+
ICloudbaseCopyFileParams,
|
|
16
|
+
ICloudbaseCopyFileResult,
|
|
17
|
+
} from '@cloudbase/types/storage'
|
|
18
|
+
|
|
19
|
+
enum EUploadMethod {
|
|
20
|
+
put = 'put',
|
|
21
|
+
post = 'post',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface IUploadMetadata {
|
|
25
|
+
url: string
|
|
26
|
+
token: string
|
|
27
|
+
authorization: string
|
|
28
|
+
fileId: string
|
|
29
|
+
cosFileId: string
|
|
30
|
+
download_url?: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const { getSdkName, ERRORS, COMMUNITY_SITE_URL } = constants
|
|
34
|
+
const { isArray, isString, isPalinObject, execCallback } = utils
|
|
35
|
+
const { catchErrorsDecorator } = helpers
|
|
36
|
+
|
|
37
|
+
export const COMPONENT_NAME = 'storage'
|
|
38
|
+
|
|
39
|
+
// function basename(path) {
|
|
40
|
+
// const lastSlashIndex = path.lastIndexOf('/')
|
|
41
|
+
// if (lastSlashIndex === -1) return path
|
|
42
|
+
// return path.slice(lastSlashIndex + 1)
|
|
43
|
+
// }
|
|
44
|
+
|
|
45
|
+
const storageGateWay = {
|
|
46
|
+
getUploadInfo: async (
|
|
47
|
+
request,
|
|
48
|
+
params: { path: string; headers?: Record<string, string> },
|
|
49
|
+
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
50
|
+
) => {
|
|
51
|
+
let res = await request.gateWay(
|
|
52
|
+
{
|
|
53
|
+
path: 'storages',
|
|
54
|
+
name: 'get-objects-upload-info',
|
|
55
|
+
data: [
|
|
56
|
+
{
|
|
57
|
+
objectId: params.path,
|
|
58
|
+
...(params.headers ? { signedHeader: params.headers } : {}),
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
customReqOpts,
|
|
63
|
+
)
|
|
64
|
+
const data = res.data?.[0] || {}
|
|
65
|
+
|
|
66
|
+
res = {
|
|
67
|
+
...res,
|
|
68
|
+
data: {
|
|
69
|
+
...(data.code ? { ...data } : {}),
|
|
70
|
+
authorization: data.authorization,
|
|
71
|
+
token: data.token,
|
|
72
|
+
url: data.uploadUrl,
|
|
73
|
+
fileId: data.cloudObjectId,
|
|
74
|
+
cosFileId: data.cloudObjectMeta,
|
|
75
|
+
download_url: data.downloadUrl,
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return res
|
|
80
|
+
},
|
|
81
|
+
getDownLoadInfo: async (
|
|
82
|
+
request,
|
|
83
|
+
params: { convertedFileList: Array<{ fileid: string }> },
|
|
84
|
+
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
85
|
+
) => {
|
|
86
|
+
let res = await request.gateWay(
|
|
87
|
+
{
|
|
88
|
+
path: 'storages',
|
|
89
|
+
name: 'get-objects-download-info',
|
|
90
|
+
data: params.convertedFileList.map((v: any) => ({ cloudObjectId: v.fileid })),
|
|
91
|
+
},
|
|
92
|
+
customReqOpts,
|
|
93
|
+
)
|
|
94
|
+
res = {
|
|
95
|
+
...res,
|
|
96
|
+
data: {
|
|
97
|
+
download_list: res.data?.map(v => ({
|
|
98
|
+
code: v.code || 'SUCCESS',
|
|
99
|
+
message: v.message,
|
|
100
|
+
fileid: v.cloudObjectId,
|
|
101
|
+
download_url: v.downloadUrl,
|
|
102
|
+
fileID: v.cloudObjectId,
|
|
103
|
+
tempFileURL: v.downloadUrl,
|
|
104
|
+
})),
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return res
|
|
109
|
+
},
|
|
110
|
+
delete: async (
|
|
111
|
+
request,
|
|
112
|
+
params: { fileList: Array<string> },
|
|
113
|
+
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
114
|
+
) => {
|
|
115
|
+
let res = await request.gateWay(
|
|
116
|
+
{
|
|
117
|
+
path: 'storages',
|
|
118
|
+
name: 'delete-objects',
|
|
119
|
+
data: params.fileList.map(v => ({ cloudObjectId: v })),
|
|
120
|
+
},
|
|
121
|
+
customReqOpts,
|
|
122
|
+
)
|
|
123
|
+
res = {
|
|
124
|
+
...res,
|
|
125
|
+
data: {
|
|
126
|
+
delete_list: res.data?.map(v => ({
|
|
127
|
+
code: v.code || 'SUCCESS',
|
|
128
|
+
fileID: v.cloudObjectId,
|
|
129
|
+
message: v.message,
|
|
130
|
+
})),
|
|
131
|
+
},
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return res
|
|
135
|
+
},
|
|
136
|
+
copyFile: async (
|
|
137
|
+
request,
|
|
138
|
+
params: {
|
|
139
|
+
convertedFileList: Array<{ src_path: string; dst_path: string; overwrite: boolean; remove_original: boolean }>
|
|
140
|
+
},
|
|
141
|
+
customReqOpts: ICloudbaseUploadFileParams['customReqOpts'],
|
|
142
|
+
) => {
|
|
143
|
+
let res = await request.gateWay(
|
|
144
|
+
{
|
|
145
|
+
path: 'storages',
|
|
146
|
+
name: 'copy-objects',
|
|
147
|
+
data: params.convertedFileList.map((v: any) => ({
|
|
148
|
+
srcPath: v.src_path,
|
|
149
|
+
dstPath: v.dst_path,
|
|
150
|
+
overwrite: v.overwrite,
|
|
151
|
+
removeOriginal: v.remove_original,
|
|
152
|
+
})),
|
|
153
|
+
},
|
|
154
|
+
customReqOpts,
|
|
155
|
+
)
|
|
156
|
+
res = {
|
|
157
|
+
...res,
|
|
158
|
+
data: {
|
|
159
|
+
copy_list: res.data?.map(v => ({
|
|
160
|
+
code: v.code || 'SUCCESS',
|
|
161
|
+
fileID: v.cloudObjectId,
|
|
162
|
+
message: v.message,
|
|
163
|
+
})),
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return res
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export interface ICloudbaseContext {
|
|
172
|
+
config: any
|
|
173
|
+
request: any
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export class CloudbaseStorage {
|
|
177
|
+
private context?: ICloudbaseContext
|
|
178
|
+
constructor(context?: ICloudbaseContext) {
|
|
179
|
+
this.context = context
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
get config() {
|
|
183
|
+
// @ts-ignore
|
|
184
|
+
return this.context?.config
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
get request() {
|
|
188
|
+
// @ts-ignore
|
|
189
|
+
return this.context?.request
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public isGateWay() {
|
|
193
|
+
// @ts-ignore
|
|
194
|
+
const { config } = this
|
|
195
|
+
const endPointMode = config.endPointMode || 'CLOUD_API'
|
|
196
|
+
|
|
197
|
+
return endPointMode === 'GATEWAY'
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@catchErrorsDecorator({
|
|
201
|
+
customInfo: {
|
|
202
|
+
className: 'Cloudbase',
|
|
203
|
+
methodName: 'uploadFile',
|
|
204
|
+
},
|
|
205
|
+
title: '上传文件失败',
|
|
206
|
+
messages: [
|
|
207
|
+
'请确认以下各项:',
|
|
208
|
+
' 1 - 调用 uploadFile() 的语法或参数是否正确',
|
|
209
|
+
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
210
|
+
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
211
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
212
|
+
],
|
|
213
|
+
})
|
|
214
|
+
public async uploadFile(
|
|
215
|
+
params: Omit<ICloudbaseUploadFileParams, 'filePath'> & { filePath?: string },
|
|
216
|
+
callback?: Function,
|
|
217
|
+
): Promise<ICloudbaseUploadFileResult> {
|
|
218
|
+
const { cloudPath, filePath, onUploadProgress, method = 'put', headers = {}, fileContent } = params
|
|
219
|
+
if (!isString(cloudPath) || (!filePath && !fileContent)) {
|
|
220
|
+
throw new Error(JSON.stringify({
|
|
221
|
+
code: ERRORS.INVALID_PARAMS,
|
|
222
|
+
msg: `[${COMPONENT_NAME}.uploadFile] invalid params`,
|
|
223
|
+
}),)
|
|
224
|
+
}
|
|
225
|
+
const uploadMethod = { put: EUploadMethod.put, post: EUploadMethod.post }[method.toLocaleLowerCase()] || EUploadMethod.put
|
|
226
|
+
|
|
227
|
+
// 调用 getUploadMetadata 获取上传元数据
|
|
228
|
+
const metadataResult = await this.getUploadMetadata({
|
|
229
|
+
cloudPath,
|
|
230
|
+
method: uploadMethod,
|
|
231
|
+
headers: uploadMethod === EUploadMethod.put ? headers : undefined,
|
|
232
|
+
customReqOpts: params.customReqOpts,
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
const { data: metadata, requestId } = metadataResult
|
|
236
|
+
const { url, authorization, token, fileId, cosFileId, download_url: downloadUrl } = metadata
|
|
237
|
+
|
|
238
|
+
const commonParams = {
|
|
239
|
+
url,
|
|
240
|
+
file: filePath,
|
|
241
|
+
name: cloudPath,
|
|
242
|
+
onUploadProgress,
|
|
243
|
+
fileContent,
|
|
244
|
+
fileId,
|
|
245
|
+
requestId,
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const putParams = {
|
|
249
|
+
...commonParams,
|
|
250
|
+
method: EUploadMethod.put,
|
|
251
|
+
headers: {
|
|
252
|
+
...headers,
|
|
253
|
+
authorization,
|
|
254
|
+
'x-cos-meta-fileid': cosFileId,
|
|
255
|
+
'x-cos-security-token': token,
|
|
256
|
+
},
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const postParams = {
|
|
260
|
+
...commonParams,
|
|
261
|
+
method: EUploadMethod.post,
|
|
262
|
+
data: {
|
|
263
|
+
key: cloudPath,
|
|
264
|
+
signature: authorization,
|
|
265
|
+
'x-cos-meta-fileid': cosFileId,
|
|
266
|
+
success_action_status: '201',
|
|
267
|
+
'x-cos-security-token': token,
|
|
268
|
+
},
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const uploadConfig = {
|
|
272
|
+
[EUploadMethod.put]: {
|
|
273
|
+
params: putParams,
|
|
274
|
+
isSuccess: (code: number) => code >= 200 && code < 300,
|
|
275
|
+
},
|
|
276
|
+
[EUploadMethod.post]: {
|
|
277
|
+
params: postParams,
|
|
278
|
+
isSuccess: (code: number) => code === 201,
|
|
279
|
+
},
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// @ts-ignore
|
|
283
|
+
const res = await this.request.upload(uploadConfig[uploadMethod].params)
|
|
284
|
+
|
|
285
|
+
if (uploadConfig[uploadMethod].isSuccess(res.statusCode)) {
|
|
286
|
+
return execCallback(callback, null, {
|
|
287
|
+
fileID: fileId,
|
|
288
|
+
download_url: downloadUrl,
|
|
289
|
+
requestId,
|
|
290
|
+
})
|
|
291
|
+
}
|
|
292
|
+
return execCallback(
|
|
293
|
+
callback,
|
|
294
|
+
new Error(`[${getSdkName()}][${ERRORS.OPERATION_FAIL}][${COMPONENT_NAME}]:${res.data}`),
|
|
295
|
+
)
|
|
296
|
+
}
|
|
297
|
+
@catchErrorsDecorator({
|
|
298
|
+
customInfo: {
|
|
299
|
+
className: 'Cloudbase',
|
|
300
|
+
methodName: 'getUploadMetadata',
|
|
301
|
+
},
|
|
302
|
+
title: '获取上传元信息失败',
|
|
303
|
+
messages: [
|
|
304
|
+
'请确认以下各项:',
|
|
305
|
+
' 1 - 调用 getUploadMetadata() 的语法或参数是否正确',
|
|
306
|
+
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
307
|
+
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
308
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
309
|
+
],
|
|
310
|
+
})
|
|
311
|
+
public async getUploadMetadata(
|
|
312
|
+
params: ICloudbaseGetUploadMetadataParams & {
|
|
313
|
+
method?: EUploadMethod
|
|
314
|
+
headers?: Record<string, string>
|
|
315
|
+
},
|
|
316
|
+
callback?: Function,
|
|
317
|
+
): Promise<{ data: IUploadMetadata; requestId: string }> {
|
|
318
|
+
const { cloudPath, method, headers } = params
|
|
319
|
+
if (!isString(cloudPath)) {
|
|
320
|
+
throw new Error(JSON.stringify({
|
|
321
|
+
code: ERRORS.INVALID_PARAMS,
|
|
322
|
+
msg: `[${COMPONENT_NAME}.getUploadMetadata] invalid cloudPath`,
|
|
323
|
+
}),)
|
|
324
|
+
}
|
|
325
|
+
// @ts-ignore
|
|
326
|
+
const { request } = this
|
|
327
|
+
const action = 'storage.getUploadMetadata'
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
let metaData: ICloudbaseFileMetaDataRes
|
|
331
|
+
|
|
332
|
+
const metaDataParam: {
|
|
333
|
+
path: string
|
|
334
|
+
method?: EUploadMethod
|
|
335
|
+
headers?: Record<string, string>
|
|
336
|
+
} = { path: cloudPath }
|
|
337
|
+
|
|
338
|
+
if (method) {
|
|
339
|
+
metaDataParam.method = method
|
|
340
|
+
}
|
|
341
|
+
if (method === EUploadMethod.put && headers) {
|
|
342
|
+
metaDataParam.headers = headers
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (this.isGateWay()) {
|
|
346
|
+
metaData = await storageGateWay.getUploadInfo(request, metaDataParam, params.customReqOpts)
|
|
347
|
+
} else {
|
|
348
|
+
metaData = await request.send(action, metaDataParam, params.customReqOpts)
|
|
349
|
+
}
|
|
350
|
+
return execCallback(callback, null, metaData)
|
|
351
|
+
} catch (err) {
|
|
352
|
+
return execCallback(callback, err)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
@catchErrorsDecorator({
|
|
356
|
+
customInfo: {
|
|
357
|
+
className: 'Cloudbase',
|
|
358
|
+
methodName: 'deleteFile',
|
|
359
|
+
},
|
|
360
|
+
title: '删除文件失败',
|
|
361
|
+
messages: [
|
|
362
|
+
'请确认以下各项:',
|
|
363
|
+
' 1 - 调用 deleteFile() 的语法或参数是否正确',
|
|
364
|
+
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
365
|
+
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
366
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
367
|
+
],
|
|
368
|
+
})
|
|
369
|
+
public async deleteFile(
|
|
370
|
+
params: ICloudbaseDeleteFileParams,
|
|
371
|
+
callback?: Function,
|
|
372
|
+
): Promise<ICloudbaseDeleteFileResult> {
|
|
373
|
+
const { fileList } = params
|
|
374
|
+
|
|
375
|
+
if (!fileList || !isArray(fileList) || fileList.length === 0) {
|
|
376
|
+
throw new Error(JSON.stringify({
|
|
377
|
+
code: ERRORS.INVALID_PARAMS,
|
|
378
|
+
msg: `[${COMPONENT_NAME}.deleteFile] fileList must not be empty`,
|
|
379
|
+
}),)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
for (const fileId of fileList) {
|
|
383
|
+
if (!fileId || !isString(fileId)) {
|
|
384
|
+
throw new Error(JSON.stringify({
|
|
385
|
+
code: ERRORS.INVALID_PARAMS,
|
|
386
|
+
msg: `[${COMPONENT_NAME}.deleteFile] fileID must be string`,
|
|
387
|
+
}),)
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const action = 'storage.batchDeleteFile'
|
|
392
|
+
// @ts-ignore
|
|
393
|
+
const { request } = this
|
|
394
|
+
let res: any = {}
|
|
395
|
+
|
|
396
|
+
if (this.isGateWay()) {
|
|
397
|
+
res = await storageGateWay.delete(request, { fileList }, params.customReqOpts)
|
|
398
|
+
} else {
|
|
399
|
+
res = await request.send(
|
|
400
|
+
action,
|
|
401
|
+
{
|
|
402
|
+
fileid_list: fileList,
|
|
403
|
+
},
|
|
404
|
+
params.customReqOpts,
|
|
405
|
+
)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (res.code) {
|
|
409
|
+
return execCallback(callback, null, res)
|
|
410
|
+
}
|
|
411
|
+
const data = {
|
|
412
|
+
fileList: res.data.delete_list,
|
|
413
|
+
requestId: res.requestId,
|
|
414
|
+
}
|
|
415
|
+
return execCallback(callback, null, data)
|
|
416
|
+
}
|
|
417
|
+
@catchErrorsDecorator({
|
|
418
|
+
customInfo: {
|
|
419
|
+
className: 'Cloudbase',
|
|
420
|
+
methodName: 'getTempFileURL',
|
|
421
|
+
},
|
|
422
|
+
title: '获取文件下载链接',
|
|
423
|
+
messages: [
|
|
424
|
+
'请确认以下各项:',
|
|
425
|
+
' 1 - 调用 getTempFileURL() 的语法或参数是否正确',
|
|
426
|
+
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
427
|
+
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
428
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
429
|
+
],
|
|
430
|
+
})
|
|
431
|
+
public async getTempFileURL(
|
|
432
|
+
params: ICloudbaseGetTempFileURLParams,
|
|
433
|
+
callback?: Function,
|
|
434
|
+
): Promise<ICloudbaseGetTempFileURLResult> {
|
|
435
|
+
const { fileList } = params
|
|
436
|
+
|
|
437
|
+
if (!fileList || !isArray(fileList) || fileList.length === 0) {
|
|
438
|
+
throw new Error(JSON.stringify({
|
|
439
|
+
code: ERRORS.INVALID_PARAMS,
|
|
440
|
+
msg: `[${COMPONENT_NAME}.getTempFileURL] fileList must not be empty`,
|
|
441
|
+
}),)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const convertedFileList = []
|
|
445
|
+
for (const file of fileList) {
|
|
446
|
+
if (isPalinObject(file)) {
|
|
447
|
+
if (!Object.prototype.hasOwnProperty.call(file, 'fileID')) {
|
|
448
|
+
throw new Error(JSON.stringify({
|
|
449
|
+
code: ERRORS.INVALID_PARAMS,
|
|
450
|
+
msg: `[${COMPONENT_NAME}.getTempFileURL] file info must include fileID`,
|
|
451
|
+
}),)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
convertedFileList.push({
|
|
455
|
+
fileid: (file as ICloudbaseFileInfo).fileID,
|
|
456
|
+
max_age: (file as ICloudbaseFileInfo).maxAge || 7200,
|
|
457
|
+
})
|
|
458
|
+
} else if (isString(file)) {
|
|
459
|
+
convertedFileList.push({
|
|
460
|
+
fileid: file,
|
|
461
|
+
})
|
|
462
|
+
} else {
|
|
463
|
+
throw new Error(JSON.stringify({
|
|
464
|
+
code: ERRORS.INVALID_PARAMS,
|
|
465
|
+
msg: `[${COMPONENT_NAME}.getTempFileURL] invalid fileList`,
|
|
466
|
+
}),)
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const action = 'storage.batchGetDownloadUrl'
|
|
471
|
+
// @ts-ignore
|
|
472
|
+
const { request } = this
|
|
473
|
+
let res: any = {}
|
|
474
|
+
|
|
475
|
+
if (this.isGateWay()) {
|
|
476
|
+
res = await storageGateWay.getDownLoadInfo(request, { convertedFileList }, params.customReqOpts)
|
|
477
|
+
} else {
|
|
478
|
+
res = await request.send(action, { file_list: convertedFileList }, params.customReqOpts)
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (res.code) {
|
|
482
|
+
return execCallback(callback, null, res)
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
return execCallback(callback, null, {
|
|
486
|
+
fileList: res.data.download_list,
|
|
487
|
+
requestId: res.requestId,
|
|
488
|
+
})
|
|
489
|
+
}
|
|
490
|
+
@catchErrorsDecorator({
|
|
491
|
+
customInfo: {
|
|
492
|
+
className: 'Cloudbase',
|
|
493
|
+
methodName: 'downloadFile',
|
|
494
|
+
},
|
|
495
|
+
title: '下载文件失败',
|
|
496
|
+
messages: [
|
|
497
|
+
'请确认以下各项:',
|
|
498
|
+
' 1 - 调用 downloadFile() 的语法或参数是否正确',
|
|
499
|
+
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
500
|
+
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
501
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
502
|
+
],
|
|
503
|
+
})
|
|
504
|
+
public async downloadFile(
|
|
505
|
+
params: ICloudbaseDownloadFileParams,
|
|
506
|
+
callback?: Function,
|
|
507
|
+
): Promise<ICloudbaseDownloadFileResult> {
|
|
508
|
+
const { fileID } = params
|
|
509
|
+
if (!isString(fileID)) {
|
|
510
|
+
throw new Error(JSON.stringify({
|
|
511
|
+
code: ERRORS.INVALID_PARAMS,
|
|
512
|
+
msg: `[${COMPONENT_NAME}.getTempFileURL] fileID must be string`,
|
|
513
|
+
}),)
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const tmpUrlRes = await this.getTempFileURL.call(this, {
|
|
517
|
+
fileList: [
|
|
518
|
+
{
|
|
519
|
+
fileID,
|
|
520
|
+
maxAge: 600,
|
|
521
|
+
},
|
|
522
|
+
],
|
|
523
|
+
customReqOpts: params.customReqOpts,
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
const res = tmpUrlRes.fileList[0]
|
|
527
|
+
|
|
528
|
+
if (res.code !== 'SUCCESS') {
|
|
529
|
+
return execCallback(callback, res)
|
|
530
|
+
}
|
|
531
|
+
// @ts-ignore
|
|
532
|
+
const { request } = this
|
|
533
|
+
|
|
534
|
+
const tmpUrl = encodeURI(res.download_url)
|
|
535
|
+
|
|
536
|
+
const result = await request.download({ url: tmpUrl, tempFilePath: params.tempFilePath })
|
|
537
|
+
return execCallback(callback, null, result)
|
|
538
|
+
}
|
|
539
|
+
@catchErrorsDecorator({
|
|
540
|
+
customInfo: {
|
|
541
|
+
className: 'Cloudbase',
|
|
542
|
+
methodName: 'copyFile',
|
|
543
|
+
},
|
|
544
|
+
title: '批量复制文件',
|
|
545
|
+
messages: [
|
|
546
|
+
'请确认以下各项:',
|
|
547
|
+
' 1 - 调用 copyFile() 的语法或参数是否正确',
|
|
548
|
+
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
|
|
549
|
+
' 3 - 云存储安全规则是否限制了当前登录状态访问',
|
|
550
|
+
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
|
|
551
|
+
],
|
|
552
|
+
})
|
|
553
|
+
public async copyFile(params: ICloudbaseCopyFileParams, callback?: Function): Promise<ICloudbaseCopyFileResult> {
|
|
554
|
+
const { fileList } = params
|
|
555
|
+
|
|
556
|
+
if (!fileList || !isArray(fileList) || fileList.length === 0) {
|
|
557
|
+
throw new Error(JSON.stringify({
|
|
558
|
+
code: ERRORS.INVALID_PARAMS,
|
|
559
|
+
msg: `[${COMPONENT_NAME}.copyFile] fileList must not be empty`,
|
|
560
|
+
}),)
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const convertedFileList = []
|
|
564
|
+
|
|
565
|
+
for (const file of fileList) {
|
|
566
|
+
const { srcPath, dstPath } = file
|
|
567
|
+
if (!srcPath || !dstPath || typeof srcPath !== 'string' || typeof dstPath !== 'string') {
|
|
568
|
+
throw new Error(JSON.stringify({
|
|
569
|
+
code: ERRORS.INVALID_PARAMS,
|
|
570
|
+
msg: `[${COMPONENT_NAME}.copyFile] srcPath and dstPath may not be empty`,
|
|
571
|
+
}),)
|
|
572
|
+
}
|
|
573
|
+
if (srcPath === dstPath) {
|
|
574
|
+
throw new Error(JSON.stringify({
|
|
575
|
+
code: ERRORS.INVALID_PARAMS,
|
|
576
|
+
msg: `[${COMPONENT_NAME}.copyFile] srcPath and dstPath can not be the same`,
|
|
577
|
+
}),)
|
|
578
|
+
}
|
|
579
|
+
// if (basename(srcPath) !== basename(dstPath)) {
|
|
580
|
+
// throw new Error(JSON.stringify({
|
|
581
|
+
// code: ERRORS.INVALID_PARAMS,
|
|
582
|
+
// msg: `[${COMPONENT_NAME}.copyFile] srcPath and dstPath file name must be the same`,
|
|
583
|
+
// }),)
|
|
584
|
+
// }
|
|
585
|
+
convertedFileList.push({
|
|
586
|
+
src_path: srcPath,
|
|
587
|
+
dst_path: dstPath,
|
|
588
|
+
overwrite: file.overwrite,
|
|
589
|
+
remove_original: file.removeOriginal,
|
|
590
|
+
})
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// @ts-ignore
|
|
594
|
+
const { request } = this
|
|
595
|
+
let res: any = {}
|
|
596
|
+
|
|
597
|
+
if (this.isGateWay()) {
|
|
598
|
+
res = await storageGateWay.copyFile(request, { convertedFileList }, params.customReqOpts)
|
|
599
|
+
} else {
|
|
600
|
+
const action = 'storage.batchCopyFile'
|
|
601
|
+
res = await request.send(action, { file_list: convertedFileList }, params.customReqOpts)
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (res.code) {
|
|
605
|
+
return execCallback(callback, null, res)
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return execCallback(callback, null, {
|
|
609
|
+
fileList: res.data.copy_list,
|
|
610
|
+
requestId: res.requestId,
|
|
611
|
+
})
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
public async getFileInfo(params: ICloudbaseGetTempFileURLParams): Promise<{
|
|
615
|
+
fileList: (Pick<ICloudbaseGetTempFileURLResult['fileList'][0], 'code' | 'fileID' | 'tempFileURL' | 'message'> & {
|
|
616
|
+
fileName?: string
|
|
617
|
+
cloudId?: ICloudbaseGetTempFileURLResult['fileList'][0]['fileID']
|
|
618
|
+
contentType?: string
|
|
619
|
+
mime?: string
|
|
620
|
+
size?: number
|
|
621
|
+
cacheControl?: string
|
|
622
|
+
lastModified?: string
|
|
623
|
+
etag?: string
|
|
624
|
+
})[]
|
|
625
|
+
requestId: string
|
|
626
|
+
}> {
|
|
627
|
+
const fileInfo = await this.getTempFileURL(params)
|
|
628
|
+
|
|
629
|
+
if (fileInfo?.fileList && fileInfo?.fileList?.length > 0) {
|
|
630
|
+
const fileList = await Promise.all(fileInfo.fileList.map(async (item: ICloudbaseGetTempFileURLResult['fileList'][0]) => {
|
|
631
|
+
if (item.code !== 'SUCCESS') {
|
|
632
|
+
return {
|
|
633
|
+
code: item.code,
|
|
634
|
+
fileID: item.fileID,
|
|
635
|
+
tempFileURL: item.tempFileURL,
|
|
636
|
+
message: item.message,
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
try {
|
|
641
|
+
// @ts-ignore
|
|
642
|
+
const { request } = this
|
|
643
|
+
const res = await request.fetch({ url: item.tempFileURL, method: 'HEAD' })
|
|
644
|
+
let { header } = res
|
|
645
|
+
|
|
646
|
+
if (Headers && header instanceof Headers) {
|
|
647
|
+
header = Object.fromEntries(res.header.entries())
|
|
648
|
+
}
|
|
649
|
+
// eslint-disable-next-line radix
|
|
650
|
+
const fileSize = parseInt(header['content-length']) || 0
|
|
651
|
+
const contentType = header['content-type'] || ''
|
|
652
|
+
|
|
653
|
+
if ([400, 404].includes(Number(res.statusCode))) {
|
|
654
|
+
return {
|
|
655
|
+
code: 'FILE_NOT_FOUND',
|
|
656
|
+
fileID: item.fileID,
|
|
657
|
+
tempFileURL: item.tempFileURL,
|
|
658
|
+
message: 'file not found',
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const fileInfo = {
|
|
663
|
+
code: item.code,
|
|
664
|
+
fileID: item.fileID,
|
|
665
|
+
tempFileURL: item.tempFileURL,
|
|
666
|
+
cloudId: item.fileID,
|
|
667
|
+
fileName: item.fileID.split('/').pop(),
|
|
668
|
+
contentType,
|
|
669
|
+
mime: contentType.split(';')[0].trim(),
|
|
670
|
+
size: fileSize,
|
|
671
|
+
etag: header.etag || '',
|
|
672
|
+
lastModified: header['last-modified'] || '',
|
|
673
|
+
cacheControl: header['cache-control'] || '',
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return fileInfo
|
|
677
|
+
} catch (e) {
|
|
678
|
+
return {
|
|
679
|
+
code: 'FETCH_FILE_INFO_ERROR',
|
|
680
|
+
fileID: item.fileID,
|
|
681
|
+
tempFileURL: item.tempFileURL,
|
|
682
|
+
message: e.message,
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}),)
|
|
686
|
+
|
|
687
|
+
return {
|
|
688
|
+
fileList,
|
|
689
|
+
requestId: fileInfo.requestId,
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
return {
|
|
694
|
+
fileList: [],
|
|
695
|
+
requestId: fileInfo.requestId,
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
}
|