"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ALiYunInstance = void 0; const tslib_1 = require("tslib"); const ali_oss_1 = tslib_1.__importDefault(require("ali-oss")); const Exception_1 = require("oak-domain/lib/types/Exception"); function getEndpoint(RegionID) { return `oss-${RegionID}.aliyuncs.com`; } const ALiYun_ENDPOINT_LIST = { 'cn-hangzhou': { ul: getEndpoint('cn-hangzhou'), }, 'cn-shanghai': { ul: getEndpoint('cn-shanghai'), }, 'cn-nanjing': { ul: getEndpoint('cn-nanjing'), }, 'cn-fuzhou': { ul: getEndpoint('cn-fuzhou'), }, 'cn-wuhan': { ul: getEndpoint('cn-wuhan'), }, 'cn-qingdao': { ul: getEndpoint('cn-qingdao'), }, 'cn-beijing': { ul: getEndpoint('cn-beijing'), }, 'cn-zhangjiakou': { ul: getEndpoint('cn-zhangjiakou'), }, 'cn-huhehaote': { ul: getEndpoint('cn-huhehaote'), }, 'cn-wulanchabu': { ul: getEndpoint('cn-wulanchabu'), }, 'cn-shenzhen': { ul: getEndpoint('cn-shenzhen'), }, 'cn-heyuan': { ul: getEndpoint('cn-heyuan'), }, 'cn-guangzhou': { ul: getEndpoint('cn-guangzhou'), }, 'cn-chengdu': { ul: getEndpoint('cn-chengdu'), }, 'cn-hongkong': { ul: getEndpoint('cn-hongkong'), }, 'us-west-1': { ul: getEndpoint('us-west-1'), }, 'us-east-1': { ul: getEndpoint('us-east-1'), }, 'ap-northeast-1': { ul: getEndpoint('ap-northeast-1'), }, 'ap-northeast-2': { ul: getEndpoint('ap-northeast-2'), }, 'ap-southeast-1': { ul: getEndpoint('ap-southeast-1'), }, 'ap-southeast-2': { ul: getEndpoint('ap-southeast-2'), }, 'ap-southeast-3': { ul: getEndpoint('ap-southeast-3'), }, 'ap-southeast-5': { ul: getEndpoint('ap-southeast-5'), }, 'ap-southeast-6': { ul: getEndpoint('ap-southeast-6'), }, 'ap-southeast-7': { ul: getEndpoint('ap-southeast-7'), }, 'ap-south-1': { ul: getEndpoint('ap-south-1'), }, 'eu-central-1': { ul: getEndpoint('eu-central-1'), }, 'eu-west-1': { ul: getEndpoint('eu-west-1'), }, 'me-east-1': { ul: getEndpoint('me-east-1'), }, 'rg-china-mainland': { ul: getEndpoint('rg-china-mainland'), }, }; class ALiYunInstance { accessKey; secretKey; constructor(accessKey, secretKey) { this.accessKey = accessKey; this.secretKey = secretKey; } getUploadInfo(bucket, zone, key) { try { const signInfo = this.getSignInfo(bucket); return { key, accessKey: this.accessKey, policy: signInfo.policy, signature: signInfo.signature, uploadHost: `https://${bucket}.${ALiYun_ENDPOINT_LIST[zone].ul}`, bucket, }; } catch (err) { throw err; } } //https://help.aliyun.com/zh/oss/user-guide/form-upload?spm=a2c4g.11186623.0.0.22147f6b1UaGxF#6ee9b6b0be6on getSignInfo(bucket) { const client = new ali_oss_1.default({ accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: bucket, }); const now = new Date(); now.setDate(now.getDate() + 1); const policy = { expiration: now.toISOString(), conditions: [ // 设置上传文件的大小限制。 ['content-length-range', 0, 5368709120], // 限制可上传的Bucket。 { bucket: bucket }, ], }; const data = client.calculatePostSignature(policy); return { policy: data.policy, signature: data.Signature, ossAccessKeyId: data.OSSAccessKeyId, }; } async removeFile(srcBucket, zone, srcKey) { const client = new ali_oss_1.default({ // oss-cn-hangzhou填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, // 填写Bucket名称。 bucket: srcBucket, }); try { // 填写Object完整路径。Object完整路径中不能包含Bucket名称。 const result = await client.delete(srcKey); return result; } catch (error) { throw error; } } async isExistObject(srcBucket, zone, srcKey) { const client = new ali_oss_1.default({ // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。 region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: srcBucket, }); let result; try { result = await client.head(srcKey); return true; } catch (error) { if (error.code === 'NoSuchKey') { return false; } throw error; } } /** * 初始化分片上传 * https://help.aliyun.com/zh/oss/developer-reference/initiate-a-multipart-upload-task */ async initiateMultipartUpload(bucket, zone, key, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: options?.accessKeyId || this.accessKey, accessKeySecret: options?.accessKeySecret || this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { const result = await client.initMultipartUpload(key, options); return { uploadId: result.uploadId, bucket: result.bucket, name: result.name, }; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 为分片上传生成预签名 URL * @param bucket 桶 * @param key 对象键 * @param uploadId 上传 ID * @param from 起始分片号 * @param to 结束分片号 * @param options 配置项 * @returns 分片预签名 URL 列表 */ async presignMulti(bucket, zone, key, uploadId, from, to, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: options?.accessKeyId || this.accessKey, accessKeySecret: options?.accessKeySecret || this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { const presignedUrls = []; const expires = options?.expires || 3600; for (let i = from; i <= to; i++) { const uploadUrl = client.signatureUrl(key, { method: 'PUT', expires: expires, subResource: { uploadId: uploadId, partNumber: String(i), }, "Content-Type": "application/octet-stream", }); presignedUrls.push({ partNumber: i, uploadUrl: uploadUrl, }); } return presignedUrls; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 准备分片上传(初始化并生成所有分片的预签名URL) * 用于前端直传场景,返回 uploadId 和每个分片的上传 URL */ async prepareMultipartUpload(bucket, zone, key, partCount, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: options?.accessKeyId || this.accessKey, accessKeySecret: options?.accessKeySecret || this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { // 1. 初始化分片上传 const initResult = await client.initMultipartUpload(key, { headers: options?.headers, timeout: options?.timeout, }); // 2. 为每个分片生成预签名 URL const parts = []; const expires = options?.expires || 3600; for (let i = 1; i <= partCount; i++) { const uploadUrl = client.signatureUrl(key, { method: 'PUT', expires: expires, subResource: { partNumber: String(i), uploadId: initResult.uploadId, }, "Content-Type": "application/octet-stream", }); parts.push({ partNumber: i, uploadUrl: uploadUrl, }); } return { uploadId: initResult.uploadId, parts: parts, }; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 上传分片 * https://help.aliyun.com/zh/oss/developer-reference/upload-parts */ async uploadPart(bucket, zone, key, uploadId, partNumber, file, start, end, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: options?.accessKeyId || this.accessKey, accessKeySecret: options?.accessKeySecret || this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { const result = await client.uploadPart(key, uploadId, partNumber, file, start ?? 0, end ?? 0, options); return { etag: result.etag, name: result.name, }; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 完成分片上传 * https://help.aliyun.com/zh/oss/developer-reference/complete-a-multipart-upload-task */ async completeMultipartUpload(bucket, zone, key, uploadId, parts, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { const result = await client.completeMultipartUpload(key, uploadId, parts, options); return { bucket: result.bucket, name: result.name, etag: result.etag, }; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 取消分片上传 * https://help.aliyun.com/zh/oss/developer-reference/abort-a-multipart-upload-task */ async abortMultipartUpload(bucket, zone, key, uploadId, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { await client.abortMultipartUpload(key, uploadId, options); } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 列举已上传的分片 * https://help.aliyun.com/zh/oss/developer-reference/list-uploaded-parts */ async listParts(bucket, zone, key, uploadId, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { const result = await client.listParts(key, uploadId, { 'max-parts': options?.['max-parts']?.toString(), 'part-number-marker': options?.['part-number-marker']?.toString(), }); return { parts: result.parts.map((part) => ({ partNumber: part.PartNumber, lastModified: part.LastModified, etag: part.ETag, size: part.Size, })), nextPartNumberMarker: result.nextPartNumberMarker, isTruncated: result.isTruncated, }; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 列举所有执行中的分片上传任务 * https://help.aliyun.com/zh/oss/developer-reference/list-initiated-multipart-upload-tasks */ async listMultipartUploads(bucket, zone, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: bucket, stsToken: options?.stsToken, }); try { const result = await client.listUploads(options || {}); return { uploads: result.uploads.map((upload) => ({ name: upload.name, uploadId: upload.uploadId, initiated: upload.initiated, })), nextKeyMarker: result.nextKeyMarker, nextUploadIdMarker: result.nextUploadIdMarker, isTruncated: result.isTruncated, }; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message, { status: error.status, }); } } /** * 获取签名URL * https://help.aliyun.com/zh/oss/developer-reference/authorize-access-4 */ async getSignedUrl(bucket, zone, key, options) { const client = new ali_oss_1.default({ region: `oss-${zone}`, accessKeyId: this.accessKey, accessKeySecret: this.secretKey, bucket: bucket, }); try { const url = client.signatureUrl(key, options); return url; } catch (error) { throw new Exception_1.OakExternalException('aliyun', error.code, error.message); } } /** * 获取预签名对象URL(统一接口) */ async presignObjectUrl(method, bucket, zone, key, options) { const url = await this.getSignedUrl(bucket, zone, key, { ...options, method, }); return { url }; } } exports.ALiYunInstance = ALiYunInstance;