UNPKG

@cloudbase/storage

Version:
359 lines (325 loc) 11 kB
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 { @catchErrorsDecorator({ 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}`)) } @catchErrorsDecorator({ 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) } } @catchErrorsDecorator({ 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) } @catchErrorsDecorator({ 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, }) } @catchErrorsDecorator({ 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) } }