209 lines
6.5 KiB
TypeScript
209 lines
6.5 KiB
TypeScript
/*
|
||
* Copyright 2025 coze-dev Authors
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
/* eslint-disable @typescript-eslint/naming-convention */
|
||
import { userStoreService } from '@coze-studio/user-store';
|
||
import {
|
||
getUploader as initUploader,
|
||
type CozeUploader,
|
||
type Config as BytedUploaderConfig,
|
||
} from '@coze-studio/uploader-adapter';
|
||
import { type developer_api } from '@coze-arch/bot-api/developer_api';
|
||
import { DeveloperApi, workflowApi } from '@coze-arch/bot-api';
|
||
|
||
export type BytedUploader = CozeUploader;
|
||
|
||
interface Inform {
|
||
uploadResult: {
|
||
Uri: string;
|
||
};
|
||
extra: string;
|
||
percent?: number;
|
||
}
|
||
|
||
type BizConfig = Record<
|
||
string,
|
||
{
|
||
getAuthToken: () => Promise<{
|
||
serviceId: string;
|
||
uploadHost: string;
|
||
stsToken: BytedUploaderConfig['stsToken'];
|
||
schema: string;
|
||
}>;
|
||
}
|
||
>;
|
||
|
||
const bizConfig: BizConfig = {
|
||
bot: {
|
||
getAuthToken: async () => {
|
||
const dataAuth = await DeveloperApi.GetUploadAuthToken({
|
||
scene: 'bot_task',
|
||
});
|
||
const dataAuthnr = dataAuth.data;
|
||
const { service_id, upload_host, auth, schema } = (dataAuthnr ||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
{}) as any;
|
||
|
||
return {
|
||
schema,
|
||
serviceId: service_id || '',
|
||
uploadHost: upload_host || '',
|
||
stsToken: {
|
||
CurrentTime: auth?.current_time || '',
|
||
ExpiredTime: auth?.expired_time || '',
|
||
SessionToken: auth?.session_token || '',
|
||
AccessKeyId: auth?.access_key_id || '',
|
||
SecretAccessKey: auth?.secret_access_key || '',
|
||
},
|
||
};
|
||
},
|
||
},
|
||
workflow: {
|
||
getAuthToken: async () => {
|
||
const dataAuth = await workflowApi.GetUploadAuthToken({
|
||
scene: 'imageflow',
|
||
});
|
||
const dataAuthnr = dataAuth.data;
|
||
|
||
const { service_id, upload_host, auth, schema } = (dataAuthnr ||
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||
{}) as any;
|
||
|
||
return {
|
||
schema,
|
||
serviceId: service_id || '',
|
||
uploadHost: upload_host || '',
|
||
stsToken: {
|
||
CurrentTime: auth?.current_time || '',
|
||
ExpiredTime: auth?.expired_time || '',
|
||
SessionToken: auth?.session_token || '',
|
||
AccessKeyId: auth?.access_key_id || '',
|
||
SecretAccessKey: auth?.secret_access_key || '',
|
||
},
|
||
};
|
||
},
|
||
},
|
||
};
|
||
|
||
export function upLoadFile({
|
||
biz = 'bot',
|
||
file,
|
||
fileType = 'image',
|
||
getProgress,
|
||
getUploader,
|
||
getUploadAuthToken,
|
||
}: {
|
||
/** 业务, 不同业务对应不同的 ImageX 服务 */
|
||
biz?: 'bot' | 'workflow' | string;
|
||
file: File;
|
||
fileType?: 'image' | 'object';
|
||
getProgress?: (progress: number) => void;
|
||
getUploader?: (uploader: BytedUploader) => void;
|
||
// 业务方自己获取upload token
|
||
getUploadAuthToken?: () => Promise<developer_api.GetUploadAuthTokenResponse>;
|
||
}) {
|
||
const config = bizConfig[biz];
|
||
if (!config && !getUploadAuthToken) {
|
||
throw new Error('upLoadFile need biz');
|
||
}
|
||
const result = new Promise<string>((resolve, reject) => {
|
||
// eslint-disable-next-line complexity
|
||
(async function () {
|
||
try {
|
||
let serviceId, uploadHost, stsToken, schema;
|
||
if (config) {
|
||
const data = await config.getAuthToken();
|
||
serviceId = data.serviceId;
|
||
uploadHost = data.uploadHost;
|
||
stsToken = data.stsToken;
|
||
schema = data.schema;
|
||
} else if (getUploadAuthToken) {
|
||
const { data } = await getUploadAuthToken();
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
serviceId = data.service_id;
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
uploadHost = data.upload_host;
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
schema = data.schema;
|
||
// cp-disable-next-line
|
||
if (uploadHost.startsWith('https://')) {
|
||
uploadHost = uploadHost.substr(8);
|
||
}
|
||
stsToken = {
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
CurrentTime: data.auth?.current_time || '',
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
ExpiredTime: data.auth?.expired_time || '',
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
SessionToken: data.auth?.session_token || '',
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
AccessKeyId: data.auth?.access_key_id || '',
|
||
// @ts-expect-error -- linter-disable-autofix
|
||
SecretAccessKey: data.auth?.secret_access_key || '',
|
||
};
|
||
}
|
||
|
||
const bytedUploader: BytedUploader = initUploader(
|
||
{
|
||
schema,
|
||
useFileExtension: true,
|
||
userId: userStoreService.getUserInfo()?.user_id_str || '',
|
||
appId: APP_ID,
|
||
// cp-disable-next-line
|
||
imageHost: `https://${uploadHost}`, //imageX上传必填
|
||
imageConfig: {
|
||
serviceId: serviceId || '', // 在视频云中申请的服务id
|
||
},
|
||
objectConfig: {
|
||
serviceId: serviceId || '',
|
||
},
|
||
imageFallbackHost: IMAGE_FALLBACK_HOST,
|
||
region: BYTE_UPLOADER_REGION,
|
||
},
|
||
IS_OVERSEA,
|
||
);
|
||
getUploader?.(bytedUploader);
|
||
bytedUploader.on('complete', inform => {
|
||
const { uploadResult } = inform;
|
||
resolve(uploadResult.Uri ?? '');
|
||
});
|
||
|
||
bytedUploader.on('error', inform => {
|
||
const { extra } = inform;
|
||
reject(extra);
|
||
});
|
||
|
||
if (getProgress) {
|
||
bytedUploader.on('progress', inform => {
|
||
const { percent } = inform as unknown as Inform;
|
||
getProgress(percent || 0);
|
||
});
|
||
}
|
||
|
||
const fileKey = bytedUploader.addFile({
|
||
file,
|
||
stsToken,
|
||
type: fileType, // 上传文件类型,三个可选值:video(视频或者音频,默认值),image(图片),object(普通文件)
|
||
});
|
||
bytedUploader.start(fileKey);
|
||
} catch (e) {
|
||
reject(e);
|
||
}
|
||
})();
|
||
});
|
||
return result;
|
||
}
|