UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

101 lines (80 loc) 2.89 kB
import urlJoin from 'url-join'; import { fileEnv } from '@/config/file'; import { S3 } from '@/server/modules/S3'; import { FileServiceImpl } from './type'; /** * 基于S3的文件服务实现 */ export class S3StaticFileImpl implements FileServiceImpl { private readonly s3: S3; constructor() { this.s3 = new S3(); } async deleteFile(key: string) { return this.s3.deleteFile(key); } async deleteFiles(keys: string[]) { return this.s3.deleteFiles(keys); } async getFileContent(key: string): Promise<string> { return this.s3.getFileContent(key); } async getFileByteArray(key: string): Promise<Uint8Array> { return this.s3.getFileByteArray(key); } async createPreSignedUrl(key: string): Promise<string> { return this.s3.createPreSignedUrl(key); } async createPreSignedUrlForPreview(key: string, expiresIn?: number): Promise<string> { return this.s3.createPreSignedUrlForPreview(key, expiresIn); } async uploadContent(path: string, content: string) { return this.s3.uploadContent(path, content); } async getFullFileUrl(url?: string | null, expiresIn?: number): Promise<string> { if (!url) return ''; // If bucket is not set public read, the preview address needs to be regenerated each time if (!fileEnv.S3_SET_ACL) { return await this.createPreSignedUrlForPreview(url, expiresIn); } if (fileEnv.S3_ENABLE_PATH_STYLE) { return urlJoin(fileEnv.S3_PUBLIC_DOMAIN!, fileEnv.S3_BUCKET!, url); } return urlJoin(fileEnv.S3_PUBLIC_DOMAIN!, url); } getKeyFromFullUrl(url: string): string { try { const urlObject = new URL(url); const { pathname } = urlObject; let key: string; if (fileEnv.S3_ENABLE_PATH_STYLE) { if (!fileEnv.S3_BUCKET) { // In path-style, we need bucket name to extract key // but if not provided, we can only guess the key is the pathname return pathname.startsWith('/') ? pathname.slice(1) : pathname; } // For path-style URLs, the path is /<bucket>/<key> // We need to remove the leading slash and the bucket name. const bucketPrefix = `/${fileEnv.S3_BUCKET}/`; if (pathname.startsWith(bucketPrefix)) { key = pathname.slice(bucketPrefix.length); } else { // Fallback for unexpected path format key = pathname.startsWith('/') ? pathname.slice(1) : pathname; } } else { // For virtual-hosted-style URLs, the path is /<key> // We just need to remove the leading slash. key = pathname.slice(1); } return key; } catch { // if url is not a valid URL, it may be a key itself return url; } } async uploadMedia(key: string, buffer: Buffer): Promise<{ key: string }> { await this.s3.uploadMedia(key, buffer); return { key }; } }