oak-external-sdk/es/service/ali/Ali.js

468 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import OSS from 'ali-oss';
import { OakExternalException, } from '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'),
},
};
export 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 OSS({
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 OSS({
// 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 OSS({
// 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 OSS({
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 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 OSS({
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 OakExternalException('aliyun', error.code, error.message, {
status: error.status,
});
}
}
/**
* 准备分片上传初始化并生成所有分片的预签名URL
* 用于前端直传场景,返回 uploadId 和每个分片的上传 URL
*/
async prepareMultipartUpload(bucket, zone, key, partCount, options) {
const client = new OSS({
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 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 OSS({
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 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 OSS({
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 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 OSS({
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 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 OSS({
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 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 OSS({
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 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 OSS({
region: `oss-${zone}`,
accessKeyId: this.accessKey,
accessKeySecret: this.secretKey,
bucket: bucket,
});
try {
const url = client.signatureUrl(key, options);
return url;
}
catch (error) {
throw new 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 };
}
}