99 lines
4.2 KiB
JavaScript
99 lines
4.2 KiB
JavaScript
import { assert } from 'oak-domain/lib/utils/assert';
|
|
import S3 from './s3';
|
|
import { S3SDK } from 'oak-external-sdk';
|
|
import { OakExternalException } from 'oak-domain/lib/types/Exception';
|
|
export default class S3Backend extends S3 {
|
|
getConfigAndInstance(application, bucket) {
|
|
const { config, account, endpoint, defaultBucket } = this.getConfig(application);
|
|
const realBucket = bucket || defaultBucket;
|
|
assert(realBucket, '没有指定上传桶,且配置中也没有默认上传桶');
|
|
// 在配置中找名称匹配的桶
|
|
const { buckets } = config;
|
|
let bucketConfig = bucket
|
|
? buckets.find((ele) => ele.name === realBucket)
|
|
: buckets[0];
|
|
const instance = S3SDK.getInstance(account.accessKey, account.secretKey, endpoint, bucketConfig?.zone || 'us-east-1');
|
|
return {
|
|
config,
|
|
instance,
|
|
endpoint,
|
|
};
|
|
}
|
|
async composeFileUrlBackend(options) {
|
|
const { application, extraFile, context, style } = options;
|
|
const { config: s3CosConfig, endpoint } = this.getConfig(application);
|
|
if (s3CosConfig) {
|
|
let bucket = s3CosConfig.buckets.find((ele) => ele.name === extraFile.bucket);
|
|
if (bucket) {
|
|
const { domain, protocol, pathStyle } = bucket;
|
|
let protocol2 = protocol;
|
|
if (protocol instanceof Array) {
|
|
const index = protocol.includes('https:')
|
|
? protocol.findIndex((ele) => ele === 'https:')
|
|
: 0;
|
|
protocol2 = protocol[index];
|
|
}
|
|
const key = this.formKey(extraFile);
|
|
// 如果使用 pathStyle (Minio 常用)
|
|
if (pathStyle && endpoint) {
|
|
return `${protocol2}//${domain}/${bucket.name}/${key}${style ? style : ''}`;
|
|
}
|
|
// 否则使用虚拟主机风格 (AWS S3 默认)
|
|
return `${protocol2}//${domain}/${key}${style ? style : ''}`;
|
|
}
|
|
}
|
|
return '';
|
|
}
|
|
async formUploadMeta(application, extraFile) {
|
|
const { bucket } = extraFile;
|
|
const key = this.formKey(extraFile);
|
|
const { instance, config: s3CosConfig, endpoint } = this.getConfigAndInstance(application, bucket);
|
|
const { buckets } = s3CosConfig;
|
|
let bucket2 = bucket;
|
|
if (!bucket2) {
|
|
const { defaultBucket } = s3CosConfig;
|
|
bucket2 = defaultBucket;
|
|
}
|
|
assert(bucket2);
|
|
const b = buckets.find((ele) => ele.name === bucket2);
|
|
assert(b, `${bucket2}不是一个有效的桶配置`);
|
|
try {
|
|
const uploadInfo = await instance.getUploadInfo(bucket2, key, endpoint, b.pathStyle);
|
|
Object.assign(extraFile, {
|
|
bucket: bucket2,
|
|
uploadMeta: uploadInfo,
|
|
});
|
|
}
|
|
catch (err) {
|
|
throw new OakExternalException(`生成S3上传信息失败: ${err.message}`);
|
|
}
|
|
}
|
|
async checkWhetherSuccess(application, extraFile) {
|
|
const { bucket } = extraFile;
|
|
const key = this.formKey(extraFile);
|
|
const { instance, config: s3CosConfig, endpoint } = this.getConfigAndInstance(application, bucket);
|
|
const b = s3CosConfig.buckets.find((ele) => ele.name === extraFile.bucket);
|
|
assert(b, `extraFile中的bucket名称在S3配置中找不到「${extraFile.bucket}」`);
|
|
try {
|
|
const result = await instance.isExistObject(extraFile.bucket, key, endpoint, b.pathStyle);
|
|
return result;
|
|
}
|
|
catch (err) {
|
|
throw err;
|
|
}
|
|
}
|
|
async removeFile(application, extraFile) {
|
|
const { bucket } = extraFile;
|
|
const key = this.formKey(extraFile);
|
|
const { instance, config: s3CosConfig, endpoint } = this.getConfigAndInstance(application, bucket);
|
|
const b = s3CosConfig.buckets.find((ele) => ele.name === extraFile.bucket);
|
|
assert(b, `extraFile中的bucket名称在S3配置中找不到「${extraFile.bucket}」`);
|
|
try {
|
|
await instance.removeFile(extraFile.bucket, key, endpoint, b.pathStyle);
|
|
}
|
|
catch (err) {
|
|
throw err;
|
|
}
|
|
}
|
|
}
|