This commit is contained in:
Xu Chang 2022-05-26 09:17:41 +08:00
parent f1445d6864
commit 826f867d0b
9 changed files with 312 additions and 0 deletions

6
lib/aspects/extraFile.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
import { GeneralRuntimeContext } from '../RuntimeContext';
import { EntityDict } from 'oak-app-domain';
export declare function getUploadInfo<ED extends EntityDict, Cxt extends GeneralRuntimeContext<ED>>(params: {
origin: string;
fileName: string;
}, context: Cxt): Promise<object>;

36
lib/aspects/extraFile.js Normal file
View File

@ -0,0 +1,36 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getUploadInfo = void 0;
const qiniu_1 = __importDefault(require("../utils/externalUpload/qiniu"));
const ExternalUploadClazz = {
qiniu: qiniu_1.default,
};
async function getUploadInfo(params, context) {
const { rowStore } = context;
const application = await context.getApplication();
const { type, config, systemId } = application;
const { origin, fileName } = params;
const { result: [system] } = await rowStore.select('system', {
data: {
id: 1,
config: 1
},
filter: {
id: systemId
}
}, context);
try {
const { config: systemConfig } = system;
const originConfig = systemConfig?.Cos[origin];
const instance = new ExternalUploadClazz[origin](originConfig);
const uploadInfo = await instance.getUploadInfo(fileName);
return uploadInfo;
}
catch (err) {
throw err;
}
}
exports.getUploadInfo = getUploadInfo;

11
lib/features/extraFile.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
import { EntityDict } from 'oak-app-domain';
import { Feature } from 'oak-frontend-base';
import { Aspect, Context } from 'oak-domain/lib/types';
export declare class ExtraFile<ED extends EntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>> extends Feature<ED, Cxt, AD> {
private rwLock;
constructor();
upload(extraFile: EntityDict['extraFile']['Schema'], scene: string): Promise<{
url: string;
bucket: string;
} | undefined>;
}

45
lib/features/extraFile.js Normal file
View File

@ -0,0 +1,45 @@
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExtraFile = void 0;
const oak_frontend_base_1 = require("oak-frontend-base");
const concurrent_1 = require("oak-domain/lib/utils/concurrent");
const uplpad_1 = require("oak-frontend-base/lib/features/uplpad");
class ExtraFile extends oak_frontend_base_1.Feature {
rwLock;
constructor() {
super();
this.rwLock = new concurrent_1.RWLock();
}
async upload(extraFile, scene) {
await this.rwLock.acquire('X');
try {
const { origin, extra1: filePath, filename: fileName } = extraFile;
const uploadInfo = await this.getAspectProxy().getUploadInfo({
origin,
fileName,
}, scene);
if (process.env.OAK_PLATFORM === 'wechatMp') {
// 微信小程序使用wx.uploadFile, 封装upload上传源为origin
const up = new uplpad_1.Upload();
const result = await up.uploadFile(origin, filePath, uploadInfo);
this.rwLock.release();
return result;
}
this.rwLock.release();
}
catch (err) {
this.rwLock.release();
throw err;
}
}
}
__decorate([
oak_frontend_base_1.Action
], ExtraFile.prototype, "upload", null);
exports.ExtraFile = ExtraFile;

28
lib/utils/externalUpload/aliyun.d.ts vendored Normal file
View File

@ -0,0 +1,28 @@
export default class aliyunInstance {
accessKey: string;
secretKey: string;
uploadHost: string;
bucket: string;
domain: string;
constructor(config: {
accessKey: string;
secretKey: string;
uploadHost: string;
bucket: string;
domain: string;
});
getUploadInfo(fileName: string): Promise<{
key: string;
signature: string;
policy: string;
uploadHost: string;
bucket: string;
domain: string;
accessKey: string;
}>;
getPolicyBase64(timeout?: number): string;
getSignature(policyBase64: string): string;
hmacSha1(encodedFlags: any, secretKey: string): string;
urlSafeBase64Encode(jsonFlags: string): string;
base64ToUrlSafe(v: string): string;
}

View File

@ -0,0 +1,73 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const buffer_1 = require("buffer");
class aliyunInstance {
accessKey;
secretKey;
uploadHost; //阿里云上传url
bucket;
domain;
constructor(config) {
const { accessKey, secretKey, uploadHost, bucket, domain } = config;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.uploadHost = uploadHost;
this.bucket = bucket;
this.domain = domain;
}
async getUploadInfo(fileName) {
try {
const { uploadHost, domain, bucket, accessKey } = this;
const key = `${Date.now()}/${fileName}`;
const policy = this.getPolicyBase64();
const signature = this.getSignature(policy);
return {
key,
signature,
policy,
uploadHost,
bucket,
domain,
accessKey,
};
}
catch (err) {
throw err;
}
}
getPolicyBase64(timeout = 8000) {
const date = new Date();
date.setHours(date.getHours() + timeout);
const policyText = {
expiration: date.toISOString(),
conditions: [
['content-length-range', 0, 5 * 1024 * 1024], // 设置上传文件的大小限制,5mb
],
};
const policyBase64 = this.urlSafeBase64Encode(JSON.stringify(policyText));
return policyBase64;
}
getSignature(policyBase64) {
const encoded = this.hmacSha1(policyBase64, this.secretKey);
;
const signature = this.base64ToUrlSafe(encoded);
return signature;
}
hmacSha1(encodedFlags, secretKey) {
const hmac = crypto_1.default.createHmac('sha1', secretKey);
hmac.update(encodedFlags);
return hmac.digest('base64');
}
urlSafeBase64Encode(jsonFlags) {
const encoded = buffer_1.Buffer.from(jsonFlags).toString('base64');
return this.base64ToUrlSafe(encoded);
}
base64ToUrlSafe(v) {
return v.replace(/\//g, '_').replace(/\+/g, '-');
}
}
exports.default = aliyunInstance;

25
lib/utils/externalUpload/qiniu.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
export default class qiniuInstance {
accessKey: string;
secretKey: string;
uploadHost: string;
bucket: string;
domain: string;
constructor(config: {
accessKey: string;
secretKey: string;
uploadHost: string;
bucket: string;
domain: string;
});
getUploadInfo(fileName: string): Promise<{
key: string;
uploadToken: string;
uploadHost: string;
bucket: string;
domain: string;
}>;
getToken(scope: string): string;
base64ToUrlSafe(v: string): string;
hmacSha1(encodedFlags: any, secretKey: string): string;
urlSafeBase64Encode(jsonFlags: string): string;
}

View File

@ -0,0 +1,66 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const buffer_1 = require("buffer");
class qiniuInstance {
accessKey;
secretKey;
uploadHost; //七牛上传url
bucket;
domain;
constructor(config) {
const { accessKey, secretKey, uploadHost, bucket, domain } = config;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.uploadHost = uploadHost;
this.bucket = bucket;
this.domain = domain;
}
async getUploadInfo(fileName) {
try {
const { uploadHost, domain, bucket } = this;
const key = `${Date.now()}/${fileName}`;
const scope = `${bucket}:${key}`;
const uploadToken = this.getToken(scope);
return {
key,
uploadToken,
uploadHost,
bucket,
domain,
};
}
catch (err) {
throw err;
}
}
getToken(scope) {
// 构造策略
const putPolicy = {
scope: scope,
deadline: 3600 + Math.floor(Date.now() / 1000),
};
// 构造凭证
const encodedFlags = this.urlSafeBase64Encode(JSON.stringify(putPolicy));
const encoded = this.hmacSha1(encodedFlags, this.secretKey);
const encodedSign = this.base64ToUrlSafe(encoded);
const uploadToken = this.accessKey + ':' + encodedSign + ':' + encodedFlags;
return uploadToken;
}
base64ToUrlSafe(v) {
return v.replace(/\//g, '_').replace(/\+/g, '-');
}
hmacSha1(encodedFlags, secretKey) {
const hmac = crypto_1.default.createHmac('sha1', secretKey);
hmac.update(encodedFlags);
return hmac.digest('base64');
}
urlSafeBase64Encode(jsonFlags) {
const encoded = buffer_1.Buffer.from(jsonFlags).toString('base64');
return this.base64ToUrlSafe(encoded);
}
}
exports.default = qiniuInstance;

22
test/test.ts Normal file
View File

@ -0,0 +1,22 @@
import { EntityDict } from 'oak-app-domain';
import { SelectRowShape } from 'oak-domain/lib/types/Entity';
function select<T extends keyof EntityDict, P extends EntityDict[T]['Selection']['data']>(entity: T, proj: P): SelectRowShape<EntityDict[T]['Schema'], P> {
throw new Error('method not implemented');
}
const r = select('address', {
id: 1,
name: 1,
detail: 1,
area: {
id: 1,
name: 1,
},
$expr10: {
$abs: 10,
},
});
r.area.name