| 15 | |
| 16 | @Injectable() |
| 17 | export class StorageService { |
| 18 | constructor(private readonly minioConfig: MinioConfig) {} |
| 19 | |
| 20 | async uploadFile( |
| 21 | fileName: string, |
| 22 | buffer: Buffer, |
| 23 | mimeType: string, |
| 24 | ): Promise<{ storageKey: string; size: number }> { |
| 25 | const client = this.minioConfig.getClient(); |
| 26 | const bucket = this.minioConfig.getBucketName(); |
| 27 | |
| 28 | // Generate unique storage key |
| 29 | const storageKey = `${randomUUID()}-${fileName}`; |
| 30 | |
| 31 | // Upload to MinIO |
| 32 | await client.putObject(bucket, storageKey, buffer, buffer.length, { |
| 33 | 'Content-Type': mimeType, |
| 34 | 'x-amz-meta-original-filename': fileName, |
| 35 | }); |
| 36 | |
| 37 | return { |
| 38 | storageKey, |
| 39 | size: buffer.length, |
| 40 | }; |
| 41 | } |
| 42 | |
| 43 | async downloadFilePreview(storageKey: string, length = 1024): Promise<Buffer> { |
| 44 | const client = this.minioConfig.getClient(); |
| 45 | const bucket = this.minioConfig.getBucketName(); |
| 46 | |
| 47 | try { |
| 48 | const stream = await client.getPartialObject(bucket, storageKey, 0, length); |
| 49 | return await this.streamToBuffer(stream); |
| 50 | } catch (error: any) { |
| 51 | if (error.code === 'NoSuchKey') { |
| 52 | throw new NotFoundException(`File not found: ${storageKey}`); |
| 53 | } |
| 54 | throw error; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | async downloadFile(storageKey: string): Promise<Buffer> { |
| 59 | const client = this.minioConfig.getClient(); |
| 60 | const bucket = this.minioConfig.getBucketName(); |
| 61 | |
| 62 | try { |
| 63 | const stream = await client.getObject(bucket, storageKey); |
| 64 | return await this.streamToBuffer(stream); |
| 65 | } catch (error: any) { |
| 66 | if (error.code === 'NoSuchKey') { |
| 67 | throw new NotFoundException(`File not found: ${storageKey}`); |
| 68 | } |
| 69 | throw error; |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | async getFileMetadata(storageKey: string): Promise<{ |
| 74 | size: number; |
nothing calls this directly
no outgoing calls
no test coverage detected