@cloudbase/storage
Version:
cloudbase js sdk storage module
359 lines (325 loc) • 11 kB
text/typescript
import { constants, utils, helpers } from '@cloudbase/utilities'
import { ICloudbase } from '@cloudbase/types'
import { ICloudbaseComponent } from '@cloudbase/types/component'
import {
ICloudbaseFileMetaDataRes,
ICloudbaseFileInfo,
ICloudbaseUploadFileParams,
ICloudbaseUploadFileResult,
ICloudbaseGetUploadMetadataParams,
ICloudbaseDeleteFileParams,
ICloudbaseDeleteFileResult,
ICloudbaseGetTempFileURLResult,
ICloudbaseGetTempFileURLParams,
ICloudbaseDownloadFileResult,
ICloudbaseDownloadFileParams,
} from '@cloudbase/types/storage'
declare const cloudbase: ICloudbase
enum EUploadMethod {
put = 'put',
post = 'post'
}
const { getSdkName, ERRORS, COMMUNITY_SITE_URL } = constants
const { isArray, isString, isPalinObject, execCallback } = utils
const { catchErrorsDecorator } = helpers
const COMPONENT_NAME = 'storage'
class CloudbaseStorage {
({
customInfo: {
className: 'Cloudbase',
methodName: 'uploadFile',
},
title: '上传文件失败',
messages: [
'请确认以下各项:',
' 1 - 调用 uploadFile() 的语法或参数是否正确',
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
' 3 - 云存储安全规则是否限制了当前登录状态访问',
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
],
})
public async uploadFile(
params: ICloudbaseUploadFileParams,
callback?: Function
): Promise<ICloudbaseUploadFileResult> {
const { cloudPath, filePath, onUploadProgress, method = 'put', headers = {} } = params
if (!isString(cloudPath) || !filePath) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.uploadFile] invalid params`,
}))
}
const uploadMethod = { put: EUploadMethod.put, post: EUploadMethod.post }[method.toLocaleLowerCase()] || EUploadMethod.put
const action = 'storage.getUploadMetadata'
// @ts-ignore
const { request } = this
const metaDataParam = {
path: cloudPath,
method: uploadMethod,
}
if (uploadMethod === EUploadMethod.put) {
/* eslint-disable-next-line */
metaDataParam["headers"] = headers
}
const metaData: ICloudbaseFileMetaDataRes = await request.send(action, metaDataParam)
const {
data: { url, authorization, token, fileId, cosFileId, download_url: downloadUrl },
requestId,
} = metaData
const commonParams = {
url,
file: filePath,
name: cloudPath,
onUploadProgress,
}
const putParams = {
...commonParams,
method: EUploadMethod.put,
headers: {
...headers,
authorization,
'x-cos-meta-fileid': cosFileId,
'x-cos-security-token': token,
},
}
const postParams = {
...commonParams,
method: EUploadMethod.post,
data: {
key: cloudPath,
signature: authorization,
'x-cos-meta-fileid': cosFileId,
success_action_status: '201',
'x-cos-security-token': token,
},
}
const uploadConfig = {
[EUploadMethod.put]: {
params: putParams,
isSuccess: (code: number) => code >= 200 && code < 300,
},
[EUploadMethod.post]: {
params: postParams,
isSuccess: (code: number) => code === 201,
},
}
const res = await request.upload(uploadConfig[uploadMethod].params)
if (uploadConfig[uploadMethod].isSuccess(res.statusCode)) {
return execCallback(callback, null, {
fileID: fileId,
download_url: downloadUrl,
requestId,
})
}
return execCallback(callback, new Error(`[${getSdkName()}][${ERRORS.OPERATION_FAIL}][${COMPONENT_NAME}]:${res.data}`))
}
({
customInfo: {
className: 'Cloudbase',
methodName: 'getUploadMetadata',
},
title: '获取上传元信息失败',
messages: [
'请确认以下各项:',
' 1 - 调用 getUploadMetadata() 的语法或参数是否正确',
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
' 3 - 云存储安全规则是否限制了当前登录状态访问',
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
],
})
public async getUploadMetadata(
params: ICloudbaseGetUploadMetadataParams,
callback?: Function
): Promise<any> {
const { cloudPath } = params
if (!isString(cloudPath)) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.getUploadMetadata] invalid cloudPath`,
}))
}
// @ts-ignore
const { request } = this
const action = 'storage.getUploadMetadata'
try {
const metaData = await request.send(action, {
path: cloudPath,
})
return execCallback(callback, null, metaData)
} catch (err) {
return execCallback(callback, err)
}
}
({
customInfo: {
className: 'Cloudbase',
methodName: 'deleteFile',
},
title: '删除文件失败',
messages: [
'请确认以下各项:',
' 1 - 调用 deleteFile() 的语法或参数是否正确',
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
' 3 - 云存储安全规则是否限制了当前登录状态访问',
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
],
})
public async deleteFile(
params: ICloudbaseDeleteFileParams,
callback?: Function
): Promise<ICloudbaseDeleteFileResult> {
const { fileList } = params
if (!fileList || !isArray(fileList) || fileList.length === 0) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.deleteFile] fileList must not be empty`,
}))
}
for (const fileId of fileList) {
if (!fileId || !isString(fileId)) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.deleteFile] fileID must be string`,
}))
}
}
const action = 'storage.batchDeleteFile'
// @ts-ignore
const { request } = this
const res = await request.send(action, {
fileid_list: fileList,
})
if (res.code) {
return execCallback(callback, null, res)
}
const data = {
fileList: res.data.delete_list,
requestId: res.requestId,
}
return execCallback(callback, null, data)
}
({
customInfo: {
className: 'Cloudbase',
methodName: 'getTempFileURL',
},
title: '获取文件下载链接',
messages: [
'请确认以下各项:',
' 1 - 调用 getTempFileURL() 的语法或参数是否正确',
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
' 3 - 云存储安全规则是否限制了当前登录状态访问',
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
],
})
public async getTempFileURL(
params: ICloudbaseGetTempFileURLParams,
callback?: Function
): Promise<ICloudbaseGetTempFileURLResult> {
const { fileList } = params
if (!fileList || !isArray(fileList) || fileList.length === 0) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.getTempFileURL] fileList must not be empty`,
}))
}
const convertedFileList = []
for (const file of fileList) {
if (isPalinObject(file)) {
if (!Object.prototype.hasOwnProperty.call(file, 'fileID')
|| !Object.prototype.hasOwnProperty.call(file, 'maxAge')) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.getTempFileURL] file info must include fileID and maxAge`,
}))
}
convertedFileList.push({
fileid: (file as ICloudbaseFileInfo).fileID,
max_age: (file as ICloudbaseFileInfo).maxAge,
})
} else if (isString(file)) {
convertedFileList.push({
fileid: file,
})
} else {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.getTempFileURL] invalid fileList`,
}))
}
}
const action = 'storage.batchGetDownloadUrl'
// @ts-ignore
const { request } = this
const res = await request.send(action, { file_list: convertedFileList })
if (res.code) {
return execCallback(callback, null, res)
}
return execCallback(callback, null, {
fileList: res.data.download_list,
requestId: res.requestId,
})
}
({
customInfo: {
className: 'Cloudbase',
methodName: 'downloadFile',
},
title: '下载文件失败',
messages: [
'请确认以下各项:',
' 1 - 调用 downloadFile() 的语法或参数是否正确',
' 2 - 当前域名是否在安全域名列表中:https://console.cloud.tencent.com/tcb/env/safety',
' 3 - 云存储安全规则是否限制了当前登录状态访问',
`如果问题依然存在,建议到官方问答社区提问或寻找帮助:${COMMUNITY_SITE_URL}`,
],
})
public async downloadFile(
params: ICloudbaseDownloadFileParams,
callback?: Function
): Promise<ICloudbaseDownloadFileResult> {
const { fileID } = params
if (!isString(fileID)) {
throw new Error(JSON.stringify({
code: ERRORS.INVALID_PARAMS,
msg: `[${COMPONENT_NAME}.getTempFileURL] fileID must be string`,
}))
}
const tmpUrlRes = await this.getTempFileURL.call(this, {
fileList: [{
fileID,
maxAge: 600,
}],
})
const res = tmpUrlRes.fileList[0]
if (res.code !== 'SUCCESS') {
return execCallback(callback, res)
}
// @ts-ignore
const { request } = this
const tmpUrl = encodeURI(res.download_url)
const result = await request.download({ url: tmpUrl })
return execCallback(callback, null, result)
}
}
const cloudbaseStorage = new CloudbaseStorage()
const component: ICloudbaseComponent = {
name: COMPONENT_NAME,
entity: {
uploadFile: cloudbaseStorage.uploadFile,
deleteFile: cloudbaseStorage.deleteFile,
getTempFileURL: cloudbaseStorage.getTempFileURL,
downloadFile: cloudbaseStorage.downloadFile,
getUploadMetadata: cloudbaseStorage.getUploadMetadata,
},
}
try {
cloudbase.registerComponent(component)
} catch (e) { }
export function registerStorage(app: Pick<ICloudbase, 'registerComponent'>) {
try {
app.registerComponent(component)
} catch (e) {
console.warn(e)
}
}